Tomcat NIO模式下的线程模型

2020-06-24  本文已影响0人  7d972d5e05e8

参考文章:断网故障时Mtop触发tomcat高并发场景下的BUG排查和修复(已被apache采纳)

给这篇文章的排查思路点个赞,排查过程很值得学习

NIO模式背景介绍

Tomcat共有三种连接器模式,BIO/NIO/APR,其中NIO是异步IO模式的简称。在默认的配置下,NIO的模式的实现模型如下:

一个典型的请求处理过程

nio_model

如图所示,是一个典型的请求处理过程。其中绿色代表线程,蓝色代表数据。

  1. Acceptor线程接受请求,从socketCache里面拿出socket对象(没有的话会创建,缓存的目的是避免对象创建的开销),
  2. Acceptor线程标记好Poller对象,组装成PollerEvent,放入该Poller对象的PollerEvent队列
  3. Poller线程从事件队列里面拿出PollerEvent,将其中的socket注册到自身的selector上,
  4. Poller线程等到有读写事件发生时,分发给SocketProcessor线程去实际处理请求
  5. SocketProcessor线程处理完请求,socket对象被回收,放入socketCache

到这里总结一下:

  1. Acceptor线程监听8080端口,发现有tcp请求要过来连接,那么内核在处理完该tcp的三次握手后,就会创建一个完整socket给到用户态。
  2. Acceptor通过轮询方式,依次把成功建立连接的socket封装成PollerEvent放到PollerEventQueue队列里面,并把该socket注册到Poller的多路复用器Selector里面,感兴趣的时间应该只有READ事件,毕竟Write事件是处理线程直接写到socket的,不走事件驱动的多路复用器。
  3. 这个时候所有已建立连接的socket都在各个Poller的多路复用器里面,等待着客户端把它们各自的请求参数数据写进来。如果某一个socket的请求数据完全写进来了,那么会触发poller的select()函数返回。这个时候Poller线程会把该socket封装成一个SocketProcessor的Runnable,提交给线程池处理。线程池的线程才是真正执行业务操作的,业务操作完成后,也是由它直接向socket写数据,不再经过事件驱动那么麻烦的处理流程了。
  4. SocketProcessor处理完请求,竟然还会把socket对象放入socketCache中,搞了个对象池。。。牛逼。
上一篇下一篇

猜你喜欢

热点阅读