基于tomcat-embed-core:9.0.60 , Http11NioProtocol(默认启用的)
【servlet3异步支持模型,下次上图】
1、tomcat关键的三种类型线程:Acceptor Thread(接收客户端连接,一个线程)、Poller Thread(轮询处理网络IO读写事件及事件队列,一个线程)、业务处理线程(线程池);
2、Acceptor Thread中的监听socket为阻塞模式,可以设置tcp全连接队列大小。创建的客户端连接会进入Poller Thread的事件队列,等待Poller Thread轮询处理。
相关源码:
启动Acceptor Thread线程:
org.apache.tomcat.util.net.AbstractEndpoint#startAcceptorThread
protected void startAcceptorThread() {
acceptor = new Acceptor<>(this);
String threadName = getName() + "-Acceptor";
acceptor.setThreadName(threadName);
Thread t = new Thread(acceptor, threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();
}
客户端连接进入Poller Thread的事件队列:
3、Poller Thread 采用Reactor模型,会处理事件队列及网络IO事件。
源码见:
org.apache.tomcat.util.net.NioEndpoint.Poller#run
网络IO事件的处理,会由业务线程池提交异步执行:
org.apache.tomcat.util.net.AbstractEndpoint#processSocket
5、每种线程类型都会有一个队列伴随,只不过Acceptor Thread的队列属于tcp全连接队列,tcp半连接队列容量可以通过操作系统配置(注意每种类型的队列容量是否受限);
6、业务处理完返回数据时,如果返回数据太大,即写缓冲区容量不够,会进入Poller Thread事件队列,注册写事件,轮询下次继续写回数据。