美文网首页
Tomcat NIO模式下的线程模型

Tomcat NIO模式下的线程模型

作者: 7d972d5e05e8 | 来源:发表于2020-06-24 17:57 被阅读0次

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

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

    NIO模式背景介绍

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

    • Acceptor线程:全局唯一,负责接受请求,并将请求放入Poller线程的事件队列。Accetpr线程在分发事件的时候,采用的Round Robin的方式来分发的
    • Poller线程:官方的建议是每个处理器配一个,但不要超过两个,由于现在几乎都是多核处理器,所以一般来说都是两个。每个Poller线程各自维护一个事件队列(无上限),它的职责是从事件队列里面拿出socket,往自己的selector上注册,然后等待selector选择读写事件,并交给SocketProcessor线程去实际处理请求。
    • SocketProcessor线程:Ali-tomcat的默认配置是250(参见server.xml里面的maxThreads),它是实际的工作线程,用于处理请求。

    一个典型的请求处理过程

    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中,搞了个对象池。。。牛逼。

    相关文章

      网友评论

          本文标题:Tomcat NIO模式下的线程模型

          本文链接:https://www.haomeiwen.com/subject/ehxdfktx.html