最近一直在解决线上一个问题,表现是:Tomcat每到凌晨会有一个高峰,峰值的并发达到了3000以上,最后的结果是Tomcat线程池满了,日志看不少请求超过了1s。服务器性能很好,Tomcat版本是7.0.54,配置以下:前端
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="3000" minSpareThreads="800"/>
<Connector executor="tomcatThreadPool" port="8084" protocol="org.apache.coyote.http11.Http11AprProtocol" connectionTimeout="60000" keepAliveTimeout="30000" maxKeepAliveRequests="8000" maxHttpHeaderSize="8192" URIEncoding="UTF-8" enableLookups="false" acceptCount="1000" disableUploadTimeout="true" redirectPort="8443" />
过后thread dump看其实真正处于RUNNABLE状态的线程不多,绝大部分线程都处于TIMED_WAITING状态:apache
因而大伙都开始纠结为何线程会涨到3000,并且发现即便峰值过了线程数并不会降下来。后端
咱们首先想到的是:后端应用的处理瞬间比较慢,“堵住了”致使前端线程数涨了起来。可是优化一个版本上线后发现虽然涨的状况有所好转,可是最终线程池仍是会达到3000这个最大值。tomcat
==================================分割线=========================================服务器
以上是大背景,中间的过程省略,直接跟各位说下目前我获得的结论:多线程
简单说下我验证的Tomcat(7.0.54)线程池大概的工做机制并发
minSapreThreads
设置的线程数至于Tomcat为何移除maxSpareThreads这个参数,我想也是出于性能的考虑,不停的收缩线程池性能确定不高,而多余的线程处于等待状态的好处是一有新请求过来马上能够处理。less
并且大量的Tomcat线程处于等待状态不会消耗CPU,可是会消耗一些JVM存储。性能
这是我如今纠结的核心。究竟是不是应用的性能慢致使的,我如今的结论是有关系,但关键是并发。 Tomcat的线程池的线程数跟你的瞬间并发有关系,好比maxThreads设置为1000,当瞬间并发达到1000那么Tomcat就会起1000个线程来处理,这时候跟你应用的快慢关系不大。 那么是否是并发多少Tomcat就会起多少个线程呢?这里还跟Tomcat的这几个参数设置有关系,看官方的解释是最靠谱的:优化
maxThreads:The maximum number of request processing threads to be created by this Connector, which therefore determines the maximum number of simultaneous requests that can be handled. If not specified, this attribute is set to 200. If an executor is associated with this connector, this attribute is ignored as the connector will execute tasks using the executor rather than an internal thread pool.
maxConnections:The maximum number of connections that the server will accept and process at any given time. When this number has been reached, the server will accept, but not process, one further connection. This additional connection be blocked until the number of connections being processed falls below maxConnections at which point the server will start accepting and processing new connections again. Note that once the limit has been reached, the operating system may still accept connections based on the acceptCount setting. The default value varies by connector type. For BIO the default is the value of maxThreads unless an Executor is used in which case the default will be the value of maxThreads from the executor. For NIO the default is 10000. For APR/native, the default is 8192.……
acceptCount:The maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused. The default value is 100.
minSpareThreads:The minimum number of threads always kept running. If not specified, the default of 10 is used.
我简单理解就是:
maxThreads
- Tomcat线程池最多能起的线程数maxConnections
- Tomcat最多能并发处理的请求(链接)acceptCount
- Tomcat维护最大的对列数minSpareThreads
- Tomcat初始化的线程池大小或者说Tomcat线程池最少会有这么多线程。比较容易弄混的是maxThreads和maxConnections这两个参数:
maxThreads是指Tomcat线程池作多能起的线程数
maxConnections则是Tomcat一瞬间作多可以处理的并发链接数。好比maxThreads=1000,maxConnections=800,假设某一瞬间的并发时1000,那么最终Tomcat的线程数将会是800,即同时处理800个请求,剩余200进入队列“排队”,若是acceptCount=100,那么有100个请求会被拒掉。
注意:根据前面所说,只是并发那一瞬间Tomcat会起800个线程处理请求,可是稳定后,某一瞬间可能只有不多的线程处于RUNNABLE状态,大部分线程是TIMED_WAITING,若是你的应用处理时间够快的话。因此真正决定Tomcat最大可能达到的线程数是maxConnections这个参数和并发数,当并发数超过这个参数则请求会排队,这时响应的快慢就看你的程序性能了。
以上的结论都是我我的验证和总结,若有不对,跪求指正!!!