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。
- maxConnections
表示最多可以有多少个socket连接到tomcat上
,也就是Acceptor能同时接受的最大连接数。当当前socket连接超过maxConnections的时候,Acceptor线程自己会阻塞等待,等连接降下去之后,才去处理Accept队列的下一个连接)。- 对于
BIO
来说,每一个建立的连接都需要一个Worker线程处理,一般maxConnections取值与maxThreads相同,默认为200(如果配置了Executor,则默认值是Executor的maxThreads)
; - 对于
NIO 和 NIO2
,由于采用了NIO的IO多路复用模型,一个Poller线程中的Selector可以同时接受和处理多个socket连接并监听事件,只有当连接中有的请求到来时才会使用Worker线程去处理。maxConnections应该配置得比maxThreads要大的多,默认情况下是10000。
- 对于
APR/native
,默认值为 8192
,并且如果配置的值不是1024的倍数,maxConnections 的实际值将减少到1024的最大倍数。
- acceptCount
acceptCount指的就是Accept队列的大小
,即OS维护的TCP完全连接队列的大小。换句话说,就是指当前同时连接数超过maxConnections的时候,还可接受的连接数。默认值为100。
- 当accept队列满了之后,client可能会返回read timeout 或者 connection reset by peer(tomcat官网说的是返回
connection refused
)。
- maxThreads
- tomcat的
Connector工作线程池的最大并发线程数量
,即同一时刻tomcat最多maxThreads个worker线程在处理通过Acceptor接收的客户端的请求。这是真正的tomcat并发数。 - maxThreads规定的是
最大的线程数目
,并不是实际running的CPU数量;实际上,maxThreads的大小比CPU核心数量要大得多。这是因为,处理请求的线程真正用于计算的时间可能很少,大多数时间可能在阻塞,如等待数据库返回数据、等待硬盘读写数据等。因此,在某一时刻,只有少数的线程真正的在使用物理CPU,大多数线程都在等待;因此线程数远大于物理核心数才是合理的。换句话说,Tomcat通过使用比CPU核心数量多得多的线程数,可以使CPU忙碌起来,大大提高CPU的利用率。 - 总之,
maxThreads数量应该远大于CPU核心数量
;而且CPU核心数越大,maxThreads应该越大;应用中CPU越不密集(IO越密集),maxThreads应该越大,以便能够充分利用CPU。当然,maxThreads的值并不是越大越好,如果maxThreads过大,那么CPU会花费大量的时间用于线程的切换,整体效率会降低。线程数的经验值为:1核2g内存为200,线程数经验值200;4核8g内存,线程数经验值800。
- tomcat的
参考资料:
- Apache Tomcat 8 Configuration Reference
- 深入理解-Tomcat-(二)-从宏观上理解-Tomcat-组件及架构
- 深度解读Tomcat中的NIO模型
- 详解tomcat的连接数与线程池
如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!
以上是关于Tomcat的acceptCountmaxConnections与maxThreads参数的含义和关系的主要内容,如果未能解决你的问题,请参考以下文章