Tomcat的acceptCountmaxConnections与maxThreads参数的含义和关系

Posted 刘Java

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat的acceptCountmaxConnections与maxThreads参数的含义和关系相关的知识,希望对你有一定的参考价值。

详细的介绍了Tomcat中的acceptCount、maxConnections与maxThreads参数的含义以及关系。

上一篇文章:Tomcat的核心组件以及server.xml配置全解【一万字】中,我们讲了acceptCount、maxConnections与maxThreads这几个参数,可能比较模糊,现在我们比较详细的介绍它们的含义以及它们之间的关系。

maxThreads(包括minSpareThreads)是tomcat工作线程池的配置参数,maxThreads就相当于jdk线程池的maxPoolSize,而minSpareThreads就相当于jdk线程池的corePoolSize,线程任务就是一个连接的请求,,每一个请求都会尝试新建要给Worder线程来处理!

acceptCount、maxConnections实际上是tcp层面的参数,因此我们需要先了解TCP建立连接的三次握手时的过程。

1 握手队列

首先,TCP的三次握手和四次挥手的一般流程图如下:

我们在此前就详细讲过了具体的流程(TCP和UDP协议以及TCP的三次握手和四次挥手),这里不再赘述。这里想要说的是,这张图中还有一些TCP连接的细节没有讲到,而这个细节真是我们现在需要学习的!

实际上,对于Client端的一个请求,Client首先发送SYN给服务端,OS(操作系统内核)会把连接信息放到要给SYN队列(SYN Queue)中,SYN队列是一个半连接队列(因为还没有真正的建立TCP连接),同时服务器返回一个SYN+ACK包给客户端,并且在没有收到ACK包时重传,直到超时。

Client收SYN+ACK包后,再次发送ACK包给服务端,三次握手成功,OS会把连接从SYN队列中移除,并创建一个完整的连接,随后将该连接加入Accept队列(Accept Queue)中,Accept队列是一个全连接队列(因为此时已经真正的建立了TCP连接),等待被上层应用程序取走的连接。当应用程序进程调用accept()系统从accept队列中获取已经建立成功的连接套接字之后,这个socket将移除Accept队列。

如下图所示:

如果Accept全队列满了之后,即使Client继续向server发送ACK的包,服务端会通过/proc/sys/net/ipv4/tcp_abort_on_overflow来决定如何响应:

# cat /proc/sys/net/ipv4/tcp_abort_on_overflow
0

0表示Server直接丢弃该ACK,Server过一段时间再次发送SYN+ACK给Client(也就是重新走握手的第二步),如果Client超时等待比较短,就会返回read timeout;1表示发送RST通知Client,Client端会返回connection reset by peer。

如果是SYN半连接队列满了,不开启syncookies的时候,服务端会丢弃新来的SYN包,而Client在多次重发SYN包得不到响应而返回connection timeout错误。但是,当Server端开启了syncookies=1,那么SYN半连接队列就没有逻辑上的最大值了。(常说的syn floods 洪水攻击就是针对半连接队列的,攻击方不停地建连接,但是建连接的时候只做第一步,第二步中攻击方收到server的syn+ack后故意扔掉什么也不做,而Server需要不断重发直至超时,浙江导致SYN队列满其他正常请求无法进来。)

SYN队列和Accept队列都是内核系统中的队列。SYN半连接队列的大小取决于max(64, /proc/sys/net/ipv4/tcp_max_syn_backlog),一般情况下无法通过高级程序语言直接控制,Accept全连接队列的大小取决于min(backlog, somaxconn),somaxconn是一个os级别的系统参数(一般默认为128),而backlog的值则可以由我们的应用程序定义,比如Java相关的Socket和tomcat都可以去定义。

Java的ServerSocket构造器的backlog参数就是指的Accept队列的大小!

/**
 * 创建服务器套接字,绑定到指定的端口。
 */
public ServerSocket(int port) throws IOException {
    this(port, 50, null);
}

/**
 * 创建服务器套接字并将其绑定到指定的端口号,并指定Accept队列大小backlog
 */
public ServerSocket(int port, int backlog) throws IOException {
    this(port, backlog, null);
}

可以看到,默认的ServerSocket的backlog为50。

2 tomcat的参数解释

对于tomcat应用程序来说,tomcat使用Acceptor线程专门负责从Accept队列中取出connection,接受该connection,然后交给工作线程去处理(读取请求参数、处理逻辑、返回响应等等)。如果该连接不是keep alived的话,则关闭该连接,然后该工作线程释放回线程池,如果是keep alived的话,则等待下一个数据包的到来直到keepAliveTimeout,然后关闭该连接释放回线程池。然后Acceptor线程接着去accept队列取connection。

  1. maxConnections
    1. 表示最多可以有多少个socket连接到tomcat上,也就是Acceptor能同时接受的最大连接数。当当前socket连接超过maxConnections的时候,Acceptor线程自己会阻塞等待,等连接降下去之后,才去处理Accept队列的下一个连接)。
    2. 对于BIO来说,每一个建立的连接都需要一个Worker线程处理,一般maxConnections取值与maxThreads相同,默认为200(如果配置了Executor,则默认值是Executor的maxThreads)
    3. 对于NIO 和 NIO2,由于采用了NIO的IO多路复用模型,一个Poller线程中的Selector可以同时接受和处理多个socket连接并监听事件,只有当连接中有的请求到来时才会使用Worker线程去处理。maxConnections应该配置得比maxThreads要大的多,默认情况下是10000。
    4. 对于APR/native默认值为 8192,并且如果配置的值不是1024的倍数,maxConnections 的实际值将减少到1024的最大倍数。
  2. acceptCount
    1. acceptCount指的就是Accept队列的大小,即OS维护的TCP完全连接队列的大小。换句话说,就是指当前同时连接数超过maxConnections的时候,还可接受的连接数。默认值为100。
    2. 当accept队列满了之后,client可能会返回read timeout 或者 connection reset by peer(tomcat官网说的是返回connection refused)。
  3. maxThreads
    1. tomcat的Connector工作线程池的最大并发线程数量,即同一时刻tomcat最多maxThreads个worker线程在处理通过Acceptor接收的客户端的请求。这是真正的tomcat并发数。
    2. maxThreads规定的是最大的线程数目,并不是实际running的CPU数量;实际上,maxThreads的大小比CPU核心数量要大得多。这是因为,处理请求的线程真正用于计算的时间可能很少,大多数时间可能在阻塞,如等待数据库返回数据、等待硬盘读写数据等。因此,在某一时刻,只有少数的线程真正的在使用物理CPU,大多数线程都在等待;因此线程数远大于物理核心数才是合理的。换句话说,Tomcat通过使用比CPU核心数量多得多的线程数,可以使CPU忙碌起来,大大提高CPU的利用率。
    3. 总之,maxThreads数量应该远大于CPU核心数量;而且CPU核心数越大,maxThreads应该越大;应用中CPU越不密集(IO越密集),maxThreads应该越大,以便能够充分利用CPU。当然,maxThreads的值并不是越大越好,如果maxThreads过大,那么CPU会花费大量的时间用于线程的切换,整体效率会降低。线程数的经验值为:1核2g内存为200,线程数经验值200;4核8g内存,线程数经验值800。

参考资料:

  1. Apache Tomcat 8 Configuration Reference
  2. 深入理解-Tomcat-(二)-从宏观上理解-Tomcat-组件及架构
  3. 深度解读Tomcat中的NIO模型
  4. 详解tomcat的连接数与线程池

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

以上是关于Tomcat的acceptCountmaxConnections与maxThreads参数的含义和关系的主要内容,如果未能解决你的问题,请参考以下文章

windows tomcat 怎么启动tomcat

怎么卸载tomcat

Tomcat工作原理

tomcat的配置问题

tomcat学习笔记Tomcat源码剖析

tomcat学习笔记Tomcat源码剖析