Jetty 服务器架构分析(下)

说过了服务器启动,最后来看一下请求处理过程, 服务器启动好后,处于待命状态,请求来了,请求处理过程由分两个建阶段:

  • 请求连接建立过程 ( NIO 为例 )

前面有提到,从线程池中固定分配了一个线程专门用于等待新连接,就是上图的监听线程,没有请求来时,该线程是阻塞在 accept () 方法上的,当新连接来建立连接时, accept 方法分配了一个 socket ,并将其设置为 nonblocking, 最后要做的就是将该 socket 丢给某个 Acceptor 线程 ( 基本上机会均等 ) 处理,然后立马返回继续处于接受状态,可以这个线程的工作是相当的简单的,效率那也是相当的高。

Acceptor 线程有很多个 ( 全部来自于线程池,并且固定分配出来,基于 jetty.xml 配置中的 Acceptors 配置数量 ) ,每个线程都维护了一个 SelectSet, 每个 SelectSet 又对应了一个 Selector, 这些线程会检测当前是否有任务来,例如检测 changes 队列中是否有任务,有并且是新连接,那么就迅速建立一个 endpoint 点负责管理这个 socket ,并注册 read 事件,后续该 selector 就会负责该连接的 read 事件监听。

对于连接很多的情况,这里分很多个 Selector 来分别监听,提高了效率。

Jetty 服务器架构分析(下)
  • 请求数据处理过程 ( NIO 为例 )
Jetty 服务器架构分析(下)

当数据发送过来时, Selector 检测到 read 事件,会立马调用 endpoint schedule() 方法,该方法目的就是从线程池分配一个 worker 线程专门来处理这个 read 事件,而自己却立马返回继续监听,可见,这里也是一个高效的处理方式。

业务线程分配成功后,负责请求的读取以及解析,如果请求是完整的,那么就开始调用 Server handle 方法 (server 本身就是一个 handler) ,开始 handler 的处理,最后调用到 SerlvetHandler ,最终交给 Servlet Filter ,开始了我们的自己应用。

后记

1、 Jetty 的模块化做得非常好,可以随时替换其中的绝大部分关键部件,也可以拆掉,例如不需要处理 Session ,可以简单配置一下即可搞定,不需要处理 Servlet, 可以不用配置 ServletHandler.

2、 jetty 采用非阻塞 IO 时,我们可以看到从头到尾的几次线程池分配情况,第一次 分配一个固定线程监听新连接,第二次 分配 N 个固定线程监听 read 事件(这里的 N 个线程在 7.3 版本中配置文件中配置 acceptors 数量即可,也就是说会从线程池固定分配 N 个线程出来),第三次 分配线程就是 read 事件到来之后,立即分配一个业务线程 ( 这个是临时的,用了要回收 ) 处理数据直到我们应用返回结果。最后有一个地方 上面都没有说到,那就是超时等原因要关闭连接时,是分配了临时线程来处理这些事情

3、 模块化、切分 task

4、 小,真的很小

延伸阅读

1、 Jetty continuations

2、 Tomcat comet

你可能感兴趣的:(tomcat,应用服务器,socket,配置管理,Comet)