写点什么

tomcat 优化——并发和 Tomcat 线程数,mysql 集群原理详解

用户头像
极客good
关注
发布于: 刚刚

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


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


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 降低了很多导致的)

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
tomcat优化——并发和Tomcat线程数,mysql集群原理详解