Tomcat NIO 模型的实现

本文深入剖析Tomcat的NIO模型实现,包括Acceptor接收连接并注册到Poller,Poller处理I/O事件,SocketProcessor的处理流程,以及如何通过BlockPoller模拟阻塞。此外,还探讨了Tomcat 8.5版本中缓存数据结构和LimitLatch的优化。
摘要由CSDN通过智能技术生成

Tomcat 对 BIO 和 NIO 两种模型都进行了实现,其中 BIO 的实现理解起来比较简单,而 NIO 的实现就比较复杂了,并且它跟常用的 Reactor 模型也略有不同,具体设计如下:

可以看出多了一个 BlockPoller 的设计,这是因为在 Servlet 规范中 ServletInputStream 和 ServletOutputStream 是阻塞的,所以请求体和响应体的读取和发送需要阻塞处理。请求行读取SSL 握手使用非阻塞的 Poller 处理。一次连接基本的处理流程是:

  • Acceptor 接收 TCP 连接,并将其注册到 Poller 上
  • Poller 发现通道有就绪的 I/O 事件,将事件分配给线程池中的线程处理
  • 线程池线程首先在 Poller 上非阻塞完成请求行和 SSL 握手的处理,然后通过容器调用 Servlet,生成响应,最后如果需要读取请求体或者发送响应,那就会将通道注册到 BlockPoller 上模拟阻塞完成

接下来分析核心代码的实现,源码来自 Tomcat 6.0.53 版本,之所以使用这个版本是因为看起来简单直观没有太多的抽象,也不影响来理解核心的处理逻辑。首先看下连接处理的方法调用情况,可右键直接打开图片查看大图:

相关类或接口的功能如下:

  • Acceptor: 阻塞监听和接收通道连接
  • Poller: 事件多路复用器,通知 I/O 事件的发生并分配合适的处理器
  • PollerEvent: 是对通道、SelectionKey 的附加对象和通道关注事件的封装
  • SocketProcessor: 线程池调度单元,它处理 SSL 握手,调用 Handler 解析协议
  • Handler: 通道处理接口,用于适配多种协议,如 HTTP、AJP
  • NioEndpoint: 服务启停初始化的入口
  • NioSelectorPool: 提供一个阻塞读写使用的 Selector 池和一个单例 Selector
  • NioBlockingSelector: 提供阻塞读和写的方法
  • BlockPoller: 与 NioBlockingSelector 配合完成模拟阻塞
  • NioChannel: 封装 SocketChannel 和读写使用的 ByteBuffer
  • KeyAttachment: Key 的附加对象,它包含通道最后访问时间和用于模拟阻塞使用的读写闭锁

1. Acceptor 注册通道到 Poller 上

Acceptor 和 Poller 分属两个不同的线程,通常情况下 Poller 阻塞在 select() 方法的调用上,此方法会锁住内部的 publicKeys 集合,所以 Acceptor 接收到通道连接不能直接注册到 Poller 上,否则会造成死锁。Tomcat 使用生产者-消费者模式来进行并发协作,缓冲区使用的是 ConcurrentLinkedQueue 无界队列。

Acceptor 接收到连接的 SocketChannel 后,将其配置成非阻塞模式,封装成 NioChannel,最后调用 getPoller0().register(NioChannel) 加入到某个 Poller 的事件队列中。

public void register(final NioChannel socket) {
  socket.setPoller(this); // 关联此 Poller
  KeyAttachment key = keyCache.poll();
  final KeyAttachment ka = key!=null?key:new KeyAttachment();
  // 重置或者初始化 KeyAttachment 对象
  ka.reset(this,socket,getSocketProperties().getSoTimeout());
  PollerEvent r = eventCache.poll();
  // 声明此通道关注的事件
  ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
  // 将此
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值