温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Tomcat NIO中整体架构是怎么样的

发布时间:2021-11-18 09:54:33 来源:亿速云 阅读:156 作者:小新 栏目:大数据

小编给大家分享一下Tomcat NIO中整体架构是怎么样的,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!



对于 tomcat NIO 来说,是由一系列框架类和数据读写类来组成的,同时这些类运行在不同的线程中,共同维持整个 tomcat NIO 架构。包括原始 socket 监听的acceptor 线程,监测注册在原始 scoket 上的事件是否发生的 poller thread 事件线程,进行数据读写和运行 servlet API 的 tomcat io 线程。当数据需要多次读写的时候,监测注册在原始 scoket 上的读写事件的 block poller 事件线程。这些类和线程共同组成的 tomcat NIO 整体结构如下所示:  

Tomcat NIO中整体架构是怎么样的

上面我们可以发现整体架构运行着4种线程:
  • Acceptor 线程
  • Poller 线程
  • Tomcat IO 线程
  • BlockPoller 线程

Acceptor线程

  • tomcat NIO 架构中会有一个 acceptor 线程,这个线程主要监听端口。当有请求过来的时候,完成 tcp 三次握手,将 accept 过来的 socket 注册OP_REGISTER 事件,并将该事件提交到 Poller 线程的事件队列 PollerEventQueue中 。


Poller线程
  • 在 tomcat NIO 架构中会有 poller 线程,在 tomcat8 及以前的版本之中,可以通过 pollerThreadCount 配置 poller thread 的数目,但是在 tomcat 9.0.21 中 poller thread 数目始终会为 1。

  • poller thread 的核心功能主要由以前文章中介绍的 Poller 类来实现,对于每一个 poller 实例都有一个 NIO selector 实例,同时也有一个事件队列SynchronizedQueue<PollerEvent>。

  • 对于每一个 poller thread 来说,都会去轮询队列 SynchronizedQueue<PollerEvent>,该队列的事件由 acceptor 线程(监听到新连接时)或者 tomcat io 线程(处理完请求之后保持长连接,添加读事件)放入,然后根据不同的事件对原始socket注册相应的读写事件。

  • 每一个poller thread 来说,会调用 java NIO 对象 selector,发起系统调用,来监测原始 scoket 是否有读写事件发生,如果有则将原始 scoket 的封装对象交由 tomcat io 线程处理。


Tomcat IO线程
  • tomcat io 线程是一个线程池,线程池大小可由 tomcat 相关参数配置。
  • tomcat io 线程会接受 poller thread 传入的 scoket 封装对象后,依次调用以前文章介绍的 SocketProcessor/ConnectionHanlder(global instance)/Http11Processor/CoyoteAdapter,最后交由 servlet container 完成servlet API 的调用。
  • 对于request header 的解析,request body 的获取,servlet API 的调用,response 数据的写入发送,这一系列过程都是在 tomcat io 线程中完成的。
  • 对于request header,request body 有时候需要多次读取操作,这个时候 tomcat io 线程会将原始 socket 再次进行读事件的注册,并交由 BlockPoller 线程处理,然后在以前文章中介绍的 readLatch (CountDownLatch) 对象上等待。
  • 对于 response data 有时候不可写,比如原始 scoket 的发送缓冲区满了,这个时候 tomcat io 线程同样会将原始 socket 再次注册写事件,并交由 BlockPoller 线程处理,然后在以前文章介绍的 writeLatch 对象上等待。


BlockPoller线程

  • tomcat NIO 架构中会有 block poller 线程,其核心功能由以前文章中介绍的 BlockPoller 类来实现,BlockPoller 实例会有一个 NIO selector 实例,同时也会拥有一个自己的事件队列实例SynchronizedQueue<Runnable>。

  • 对于BlockPoller thread来说, 会去轮询队列 SynchronizedQueue<Runnable>,该队列的对象(RunnableAdd类型)由 tomcat io 线程放入,然后根据不同的对象对原始 socket 注册相应的读写事件。

  • 对于BlockPoller thread来说, 会调用 java NIO 对象 selector,发起系统调用,来监测原始 scoket 是否有读写事件发生。如果有,则将以前文章介绍的在 readLatch 或者 writeLatch 对象上等待的 tomcat io 线程唤醒,然后 tomcat io 线程继续完成读写操作。

看完了这篇文章,相信你对“Tomcat NIO中整体架构是怎么样的”有了一定的了解,如果想了解更多相关知识,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI