tomcat 优化——并发和 Tomcat 线程数,mysql 集群原理详解
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 状态:
于是大伙都开始纠结为什么线程会涨到 3000,而且发现即使峰值过了线程数并不会降下来。
我们首先想到的是:后端应用的处理瞬间比较慢,“堵住了”导致前端线程数涨了起来。但是优化一个版本上线后发现虽然涨的情况有所好转,但是最终线程池还是会达到 3000 这个最大值。
==================================分割线=========================================
以上是大背景,中间的过程省略,直接跟各位说下目前我得到的结论:
1、首先是为什么线程不释放的问题?
简单说下我验证的 Tomcat(7.0.54)线程池大概的工作机制
Tomcat 启动时如果没有请求过来,那么线程数(都是指线程池的)为 0;
一旦有请求,Tomcat 会初始化 minSapreThreads 设置的线程数;
Tomcat 会停止长时间闲置的线程。Tomcat 还有一个参数叫 maxIdleTime:
其实从这个参数解释也能看出来 Tomcat 会停止闲置了超过一定时间的线程的,这个时间就是 maxIdleTime。但我之前的测试中确实没有发现线程释放的现象,这是为什么呢?我发现除了这个参数线程池线程是否释放?释放多少?还跟当前 Tomcat 每秒处理的请求数(从 Jmeter 或 LoadRunner 来看可以理解为 TPS)有关系。通过下表可以清晰的看出来线程数,TPS 和 maxIdleTime 之间的关系:
<table border="0"><tbody><tr><td><strong>TPS </strong></td><td><strong>maxIdleTime(ms)</strong></td><td><strong>Thread Count</strong></td></tr><tr><td>10</td><t
d>60,000</td><td>600</td></tr><tr><td>5</td><td>60,000</td><td>300</td></tr><tr><td>1</td><td>60,000</td><td><p>60</p></td></tr></tbody></table>
依次类推,当然 Thread Count 这一列是一个大约数,上下相差几个,但基本符合这样一个规则:
Thread Count = min(max((TPS * maxIdleTime)/1000,minSpareThreads),maxThreads)
当然这个 Thread Count 不会小于 minSpareThreads,这个跟之前的结论还是一样的。我现在大胆猜测下(回头看源码验证下,或者哪位同学知道告诉我下,谢谢):
Tomcat 线程池每次从队列头部取线程去处理请求,请求完结束后再放到队列尾部,也就是说前后两次请求处理不会用同一个线程。某个线程闲置超过 maxIdleTime 就释放掉。
假设首先线程池在高峰时期暴涨到 1000,高峰过后 Tomcat 处理一次请求需要 1s(从 Jmeter 看 TPS 大约就为 1),那么在 maxIdleTime 默认的 60s 内会用到线程池中 60 个线程,那么最后理论上线程池会收缩到 60(假设 minSpareThreads 大于 60)。另外:这个跟用不用 Keep-Alive 没关系(之前测试结论是因为用了 Keep-Alive 导致程序性能下降,TPS 降低了很多导致的)
评论