Jetty 的架构
组件化架构
Jetty Server 由若干 Connector、Handler,以及一个线程池组成。
Jetty = HTTP 服务器 + Servlet 容器,Connector 组件和 Handler 组件分别来实现这两个功能。这两个组件工作时所需要的线程资源都直接从一个全局线程池 ThreadPool 中获取。
Jetty 和 Tomcat 本质都是组件化的架构。
Tomcat 设计了容器来组织这些组件。运用了接口、抽象基类、组合模式。
Jetty 设计了类层次来组织这些组件。运用接口、抽象基类、模板模式。
为了管理这些组件,它们都提供了 Server 作为组件的载体。
为了Jetty 提供了一个 Server 类来启动和协调上面的核心组件。Server 创建并初始化 Connector、Handler、ThreadPool 组件,然后调用 start 方法启动这些组件。
架构区别
一个 Tomcat 实例可以配置多个 Service,不同的 Service 通过不同的连接器监听不同的端口;而 Jetty 中 Connector 是被所有 Handler 共享的。
在 Tomcat 中每个连接器都有自己的线程池,而在 Jetty 中所有的 Connector 共享一个全局的线程池。
Connector
Connector 的组成
跟 Tomcat 一样,Connector 的主要功能是对 I/O 模型和应用层协议的封装。服务端在 I/O 通信上主要完成了三件事情:监听连接、I/O 事件查询以及数据读写。因此 Jetty 设计了 Acceptor、SelectorManager 和 Connection 来分别做这三件事情。
Connector 的 I/O 模型
I/O 模型方面,最新的 Jetty 9 版本只支持 NIO,因此 Jetty 的 Connector 设计有明显的 Java NIO 通信模型的痕迹。
应用层协议方面,跟 Tomcat 的 Processor 一样,Jetty 抽象出了 Connection 组件来封装应用层协议的差异。
Jetty的 I/O 线程模型更像 Netty,Jetty 的 EatWhatYouKill 线程策略,其实就是Netty 4.0中的线程模型。
Jetty 的 Connector 只支持 NIO 模型,跟 Tomcat 的 NioEndpoint 组件一样,它也是通过 Java 的 NIO API 实现的。
Java NIO
Java NIO 有三个关键组件:Channel、Buffer 和 Selector,核心是 Selector。为了方便使用,Jetty 在原生 Selector 组件的基础上做了一些封装,实现了 ManagedSelector 组件。
Connector 与 NioEndpoint
Connector 包含了应用层协议部分。就线程模型而言,Tomcat 的 NioEndpoint 跟 Jetty 的 Connector 是相似的,都是用一个 Acceptor 数组监听连接,用一个 Selector 数组侦测 I/O 事件,用一个线程池执行请求。
它们的不同点在于,Jetty 使用了一个全局的线程池,所有的线程资源都是从线程池来分配。
Jetty Connector 设计的一大特点是,使用了回调函数来模拟异步 I/O,比如 Connection 向 EndPoint 注册了一堆回调函数。它的本质将函数当作一个参数来传递,告诉对方,你准备好了就调这个回调函数。
Node.js里也是类似的思想,到处都是callback,之后进化到了promise。
补充
IO通信的三阶段
三阶段是接受连接,等待 IO 事件发生,消费数据。
具体的实现???acceptor、selector、connection。
服务端程序的本质
https://time.geekbang.org/column/article/99770
问题
1 多个 acceptor 监听同一个 fd,当 IO 事件到来时,具体通知哪个事件呢?