记一次Tomcat线程数量异常

1,400 阅读2分钟

我们有一个核心应用的单台机器日常的QPS大约在900,线程总数大约在500。有一次发现了线上的总线程数达到了1000+。虽然平均响应时间(2ms)没有上升,但是还是值得调查一下。

首先从CAT上查看了threadDump,发现其中大部分都是http的线程。而这些也都是tomcat启动的。tomcat的配置文件如下:

<Service name="Catalina"> 

 <Executor name="tomcatThreadPool" namePrefix="catalina-exec-" 

 maxThreads="1500"  

 minSpareThreads="100"   

 maxIdleTime="60000"  

 maxQueueSize="Integer.MAX_VALUE" 

 prestartminSpareThreads="false" 

 threadPriority="5" className="org.apache.catalina.core.StandardThreadExecutor"/>

maxThreads
注:池中最大线程数。

minSpareThreads
注:活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。

maxIdleTime
注:线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒。

后来又查看了多个机器,发现线程数多的机器都集中在其中一个机房,怀疑和机房的网络有关。于是便追溯到线程飙升的时间点发现,当时确实是网络有波动,导致响应时间飙升(>10ms)。因此在QPS不变的情况下,便需要更多的线程来处理这些请求。

找到了线程的飙升的原因,不禁有个疑问:为啥过了那个时间点,线程不会下去?原因是:有maxIdleTime 这个参数的限制,默认60s。只有空闲超过60s的线程才会被销毁。

看了下tomcat线程池的管理源码:


这是创建Executor的地方,里面用到了ThreadPoolExecutor,是tomcat中的线程池管理类,其实它是继承了JDK的ThreadPoolExecutor


使用JDK的ThreadPoolExecutor进行线程管理。

具体的执行方法:


因此,通过这次的异常分析,了解了一些关于tomcat与JDK线程池相关的知识。