转载

深入拆解Tomcat&Jetty(八)

前面的学习记录已经对Tomcat整体的架构和工作原理有基本了解.但是Servlet容器不止有Tomcat,还有后来者 Jetty

Jetty与Tomcat一样都是 HTTP服务器+Servlet容器 ,Jetty与Tomcat的架构上有很多类似的地方,但是Jetty更为轻量,更容易定制.

Google App Engine采用了Jetty作为Web容器

Jetty整体架构

深入拆解Tomcat&Jetty(八)

Jetty主要由多个 连接器(Connector) ,多个 处理器(Handler) ,以及一个线程池组成.

Jetty与Tomcat一样会分为HTTP服务器部分和Servlet容器部分,分别由Connector和Handler实现,而这两个组件会共用同一个线程池的资源.

Jetty可以通过多个不同的 Connector 接收不同端口的请求, Handler 组件也可以是一个或多个,甚至不配置 Handler

Jetty提供一个 Server 类来协调各个组件.

整体架构上Tomcat与Jetty的区别

  • Tomcat会有多个Service用于对应不同的端口请求,Jetty没有Service概念,Connector是被多个Handler共享的
  • Tomcat每个连接器都有自己的线程池,而Jetty所有的Connector都共享一个全局连接池

Connector组件

Connector主要功能是对IO模型和应用层协议的封装,最新的Jetty9只支持NIO,所以底层实现都是基于NIO.Connector主要完成三件事:接收连接,IO事件查询,数据读写.分别对应 Acceptor , SelectorManage , Connection

由于Jetty的Connector都是基于NIO,所以NIO是基础. NIO回顾

Acceptor

Acceptor用于接收请求,用线程池处理连接请求,通过阻塞的方式接受连接.

ServerSocketChannel#accepet方法是阻塞的,返回后才能继续非阻塞处理

当连接创建后,会将SocketChannel设置为非阻塞模式,然后交给 Selector 处理后续任务.

SelectorManager

Jetty内部的Selector由SelectorManager进行管理,而被管理的Selector被包装为 ManagedSelector .SelectorManager内部有一个数组用于保存 ManagedSelector .

ManagedSelector 内部,会有如下流程

  • 1.将Channel注册到Selector,拿到一个SelectionKey(相当于凭证),
  • 2.创建 EndPointConnection ,和 SelectionKey 三者绑定在一起.

这个过程相当于下单(注册IO事件),下单后返回一个订单ID(Channel注册到selector,返回SelectionKey),然后通过订单完成后(IO事件触发),通过订单ID通知订单完成(调用绑定在SelectionKey上的EndPoint的方法)

ManagedSelector并不会真正处理处理,而是通过EndPoint的方法返回Runnable,再通过线程池去执行,在Runnable里面才会真正读数据和处理请求

Connection

Jetty的Connection组件类似于Tomcat的Processor,负责具体协议的解析,得到Request对象,调用Handler进行处理.

HttpConnection 是Connection的一个实现类,也实现了Runnable,在HTTPConnection中,Endpoint会注册一个回调,当数据到了EndPoint就会回调给HttpConnection,在回调方法里面会调用Endpoint接口读数据,然后让HTTP解析器解析字节流,HTTP解析器将解析后的数据包装成 Request 对象.

响应处理:Connection调用Handler,Handler通过Response对象操作响应流,往响应内容写数据,HttpConnection通过Endpoint把数据写到Channel,完成响应.

Connector工作流程

深入拆解Tomcat&Jetty(八)
  • 1.Acceptor监听连接请求,当有请求到达时就接受请求,一个连接对应一个Channel,Acceptor将Channel交给ManagedSelector处理
  • 2.ManagedSelector把Channel注册到Selector上,并创建Endpoint和Connection与Channel绑定,然后不断检测IO事件
  • 3.IO事件到达后调用Endpoint方法拿到Runnable,交给线程池执行
  • 4.线程池执行Runnable
  • 5.Runnable执行,调用回调函数,这个函数是Connection注册到Endpoint中的,
  • 6.回调函数调用EndPoint接口读取数据
  • 7.Connection解析读到的数据,生成Request对象交给Handler组件进行处理.

Jetty小结

Jetty Server在设计上只是多个Connector,多个Handler,以及一个全局线程池组成.

Jetty通过原生的NIO实现自己的IO模型,Jetty将NIO中的Selector封装成ManagedSelector方便使用.

Jetty在线程模型上与Tomcat的NioEndPoint类似,都是持有一个Acceptor数组,用一个Selector监听IO事件进行事件派发,然后用线程池执行请求.

最大的不同是Jetty全局只有一个线程池,所有的多线程任务都是由这个线程池进行处理.

Jetty Connector使用回调函数来模拟异步IO

原文  https://juejin.im/post/5e89403251882573af79a362
正文到此结束
Loading...