当前位置: 代码迷 >> 综合 >> tomtcat启动过程中看,connection-timeout,threads.max,accept-count三个参数的含义
  详细解决方案

tomtcat启动过程中看,connection-timeout,threads.max,accept-count三个参数的含义

热度:17   发布时间:2023-11-14 22:46:02.0

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含义即为该线程最大线程数。

  相关解决方案