Tomcat8之后,针对Http协议默认使用org.apache.coyote.http11.Http11NioProtocol,也就是NIO模式。通过之前的博客分析,我们知道Connector组件在初始化和start的时候会触发它子组件(Http11NioProtocol、NIOEndpoint的初始化和start)。
NIO模式工作时序图#
还是像之前那样,我们先整理出NIO模式启动时的时序图。
从上面的时序图可以看出,整个流程的重点时在NioEndpoint这个类中。下面我们通过源代码看下这几个重点方法。
Copy
//NIO模式绑定端口
public void bind() throws Exception {
//初始化套接字服务,需要注意的是在NIO模式下,这个ServerSocketChannel还是阻塞模式的
initServerSocket();
//设置默认的acceptor线程数,默认是1个,这个参数暂时好像没法修改(??)
//注意这个参数和acceptCount(接收请求连接的数量)之间的区别
if (acceptorThreadCount == 0) {
acceptorThreadCount = 1;
}
//设置pollerThreadCount,根据CPU的核数来,CPU大于2个设置为2,否则为1
if (pollerThreadCount <= 0)
pollerThreadCount = 1;
}
//设置CountDownLatch
setStopLatch(new CountDownLatch(pollerThreadCount));
initialiseSsl();
selectorPool.open();
}
这个代码主要做了些初始化工作,初始化套接字服务,初始化acceptorThreadCount和pollerThreadCount等。
再看看startInternal代码:
Copy
@Override
public void startInternal() throws Exception {
if (!running) {
running = true;
paused = false;
//创建3个缓存
//频繁创建SocketProcessor成本高
processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());
//一般情况下,我们自己不配置线程池,所以会进入这个方法,也可以自己在server.xml中配置这个线程池。
if ( getExecutor() == null ) {
//创建一个核心线程数是10,最大线程数是200,队列长度是Integer.MaxValue的线程池
//注意下,这边线程池的逻辑和JDK中线程池的逻辑不一样,