前面的学习记录已经对Tomcat整体的架构和工作原理有基本了解.但是Servlet容器不止有Tomcat,还有后来者 Jetty
Jetty与Tomcat一样都是 HTTP服务器+Servlet容器 ,Jetty与Tomcat的架构上有很多类似的地方,但是Jetty更为轻量,更容易定制.
Google App Engine采用了Jetty作为Web容器
Jetty主要由多个 连接器(Connector)
,多个 处理器(Handler)
,以及一个线程池组成.
Jetty与Tomcat一样会分为HTTP服务器部分和Servlet容器部分,分别由Connector和Handler实现,而这两个组件会共用同一个线程池的资源.
Jetty可以通过多个不同的 Connector
接收不同端口的请求, Handler
组件也可以是一个或多个,甚至不配置 Handler
Jetty提供一个 Server
类来协调各个组件.
整体架构上Tomcat与Jetty的区别
Connector主要功能是对IO模型和应用层协议的封装,最新的Jetty9只支持NIO,所以底层实现都是基于NIO.Connector主要完成三件事:接收连接,IO事件查询,数据读写.分别对应 Acceptor
, SelectorManage
, Connection
由于Jetty的Connector都是基于NIO,所以NIO是基础. NIO回顾
Acceptor用于接收请求,用线程池处理连接请求,通过阻塞的方式接受连接.
ServerSocketChannel#accepet方法是阻塞的,返回后才能继续非阻塞处理
当连接创建后,会将SocketChannel设置为非阻塞模式,然后交给 Selector
处理后续任务.
Jetty内部的Selector由SelectorManager进行管理,而被管理的Selector被包装为 ManagedSelector
.SelectorManager内部有一个数组用于保存 ManagedSelector
.
在 ManagedSelector
内部,会有如下流程
EndPoint
和 Connection
,和 SelectionKey
三者绑定在一起. 这个过程相当于下单(注册IO事件),下单后返回一个订单ID(Channel注册到selector,返回SelectionKey),然后通过订单完成后(IO事件触发),通过订单ID通知订单完成(调用绑定在SelectionKey上的EndPoint的方法)
ManagedSelector并不会真正处理处理,而是通过EndPoint的方法返回Runnable,再通过线程池去执行,在Runnable里面才会真正读数据和处理请求
Jetty的Connection组件类似于Tomcat的Processor,负责具体协议的解析,得到Request对象,调用Handler进行处理.
HttpConnection
是Connection的一个实现类,也实现了Runnable,在HTTPConnection中,Endpoint会注册一个回调,当数据到了EndPoint就会回调给HttpConnection,在回调方法里面会调用Endpoint接口读数据,然后让HTTP解析器解析字节流,HTTP解析器将解析后的数据包装成 Request
对象.
响应处理:Connection调用Handler,Handler通过Response对象操作响应流,往响应内容写数据,HttpConnection通过Endpoint把数据写到Channel,完成响应.
Jetty Server在设计上只是多个Connector,多个Handler,以及一个全局线程池组成.
Jetty通过原生的NIO实现自己的IO模型,Jetty将NIO中的Selector封装成ManagedSelector方便使用.
Jetty在线程模型上与Tomcat的NioEndPoint类似,都是持有一个Acceptor数组,用一个Selector监听IO事件进行事件派发,然后用线程池执行请求.
最大的不同是Jetty全局只有一个线程池,所有的多线程任务都是由这个线程池进行处理.