tomtcat启动过程中看,connection-timeout,threads.max,accept-count三个参数的含义
1、先从 tomcata初始化入手
入口:springboot为web环境的情况下,applicationContext实例为AnnotationConfigServletWebServerApplicationContext
SpringApplication启动过程中 执行refreshContext,调用applicationContext.refresh方法
refreshContext(context);
紧接着执行spring 生命周期接口
org.springframework.context.support.DefaultLifecycleProcessor#onRefresh
…省略若干步骤…
tomcat server启动
org.springframework.boot.web.embedded.tomcat.TomcatWebServer#start
…省略若干步骤…
关键类NioEndpoint
public void bind() throws Exception {// 关键 创建 nio sokcet 并绑定端口initServerSocket();}
进入 initServerSocket()方法
protected void initServerSocket() throws Exception {//创建新的socketserverSock = ServerSocketChannel.open();//为socket设置配置连接超时时间,read缓冲区大小等属性。socketProperties.setProperties(serverSock.socket());InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());//监听端口,注意第二个参数 就是,下面详细说serverSock.socket().bind(addr,getAcceptCount());//设置 阻塞,监听时,在未接收到可accept的新连接时,阻塞线程serverSock.configureBlocking(true);}
2、server.tomcat.accept-count含义
看下 socket的bind方法的第二个参数,backlog,调用方处传值即为accept-count
backlog的定义是已经建立tcp连接但未进行accept处理的SOCKET队列大小,已是(并非syn的SOCKET队列)。如果这个队列满了,将会发送一个ECONNREFUSED错误信息给到客户端,即 “Connection refused”
3、server.tomcat.connection-timeout含义
关键类 org.apache.tomcat.util.net.Acceptor
Acceptor.run方法循环accept新连接
// 阻塞等待新连接socket = endpoint.serverSocketAccept();// 设置socket属性if (!endpoint.setSocketOptions(socket)) {endpoint.closeSocket(socket);}
再看 org.apache.tomcat.util.net.NioEndpoint#setSocketOptions
protected boolean setSocketOptions(SocketChannel socket) {NioSocketWrapper socketWrapper = null;// 设置等待读写事件非阻塞,依赖selector轮询socket.configureBlocking(false);//设置属性socketProperties.setProperties(socket.socket());//设置连接读事件超时时间,超时自动断开连接socketWrapper.setReadTimeout(getConnectionTimeout());//设置连接写事件超时时间,超时自动断开连接socketWrapper.setWriteTimeout(getConnectionTimeout());//设置一次连接的最大请求数socketWrapper.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());//将socket注册到selector,轮询read事件poller.register(channel, socketWrapper);}
其中getConnectionTimeout()的值即为server.tomcat.connection-timeout,代表一条tcp连接在指定时间内,无读写,将断开连接,线程任务最终执行方法为org.apache.tomcat.util.net.NioEndpoint.Poller#timeout
4、server.tomcat.threads.max含义
轮询select系统调用,取出可读socket,org.apache.tomcat.util.net.NioEndpoint.Poller#run
while (true) {····省略代码····//系统调用select,取出读写事件 keyCount = selector.selectNow();//根据socketchannel当前状态,切换到下一状态,例如,OP_REGISTER=>OP_READevents();//检测超时连接timeout(0, false);···省略代码····//取出可read的channelwhile (iterator != null && iterator.hasNext()) {SelectionKey sk = iterator.next();NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();iterator.remove();//交给线程池处理该read事件processKey(sk, socketWrapper);}}
从processKey(sk, socketWrapper);进入org.apache.tomcat.util.net.AbstractEndpoint#processSocket方法
public boolean processSocket(SocketWrapperBase<S> socketWrapper,SocketEvent event, boolean dispatch) {Executor executor = getExecutor();if (dispatch && executor != null) {executor.execute(sc);}
}
代码中的executor线程池在创建时maximumPoolSize的值即为erver.tomcat.threads.max。,所有http请求,都由这个线程池执行,threads.max含义即为该线程最大线程数。