系统分析记录-rocketmq导致jvm线程数量大
一 . 系统说明:
A系统阿里云平台,5台集群,每台:1-2核,内存6G,带宽上限2M,磁盘1G。
基于tomcat容器,主要业务消费rocketmq,再pegion(服务治理工具)调用第三方服务。
同时接入20个左右topic的mq,并每一次mq都会调用一次第三方服务,第三方服务有B,C,D等系统,单台mq的qps 有几个(4个)比较大,一小时几十万。其他的比较小。
二. 问题:
(5台集群一台的线程数量达到2500+,触发公司线程报警。其他四台也很高(2000+),但是还没到阀值。)线程数量超标,且有很少部分调用失败,分析调用失败原因,分析下线程分别是哪些,为何线程会这么多,能否减少。
三 .初步分析:
1. 调用链
看到线程数量大的这台a机器,调用B系统有多个请求时间到15S(调用超时时间是5S),并有10个左右调用失败,正常的都是1S以下,但是B系统的日志显示所有请求都是1S以下返回的。目前没有思路。-调用失败大概率只是性能卡住超时,解决线程数量应该就可以,且数量不多,可以后续再看。
2. threaddump -看所有线程信息
2.1 活跃线程:
226个running Threads,194 个 "New I/O worker": running, holding...",活跃线程大部分是在epoolwait,应该是等着接收mq消息。

2.2 全部线程:


1900+个线程都在线程池里空闲着,等待任务来执行-线程数量多,但这么多闲着等待的,问题似乎就在这里了。
空闲线程分析--大致是:ConsumeMessageThread_X 有275个,NettyClientPublicExecutor_X 1024个,600+ 个线程池模样线程(pool-XX-thread-XXX)。
分别分析下 :
(1)ConsumeMessageThread_X 是rocketmq的消费线程,epoolwait中,所以ConsumeMessageThread_X 也在等待。
数量上参考下rocketmq源码,在:


有二十个个消费客户端,每个最少20个线程,相乘,基本也是这个数量。空闲等待率一半差不多就是这么多了。
这里线程数量不算特别多,但是空闲的有点多,所以不需要初始就20个,有些mq真的qps超级小。
包装消费类时可以在start方法前面,set这两个值。并对外提供配置方式。,默写低并发mq默认的最小值有点大可以适当配置减少(例如改成5)。
(2)NettyClientPublicExecutor_X,NettyRemoteingClient.java :这个线程是client做回调用的。

private int clientCallbackExecutorThreads = Runtime.getRuntime().availableProcessors();
所以应该是 可用processor有64个

64 * 16 = 1024 -这是最多的线程数量。
netty里默认新建线程池用物理服务器的16 个cpu* 每个的可用核数量, 云服务器是很多虚拟服务器公用物理服务器,是超级高配置的服务器,可达16个cpu*64核。
其实这部分线程只做callback使用,不需要很多数量,这里中间件的数量应该也可以开发可配置,而不是用默认的cpu*核心的方式来新建线程。
(3)pool-XX-thread-XXX
有5(7,21,22,15,28)个线程池,每个线程池100+个线程,都是线程池里的线程空闲。
这部分需要看下pegion的代码,惊奇地发现pegion这部分跟dubbo一样,近似看下开源的dubbo的代码

大意就是各种threadpool用这个factory来生成线程,线程越来越多。没有源码很难看懂,从数量看也不是特别多,目前不知道为何会一直新建线程。
如果猜测下应该是调用外系统超时导致多起了一些线程来处理,后续线程未释放掉,可能中间件没有在新建线程后再减少的操作。
遗留问题和思考:
rocketmq不常用线程数量可以配置等方式减少下-这次改配置,以后是不是都要改。
dubbo pegion线程池数量等有场景再分析下-线程池的600+没搞懂原因,继续观察。其他线程数量少了后,这里似乎没有再现很多线程,可能真的是被连带的。
dubbo个别服务调用时间长,这个目前还没有思路,也没详细分析,猜测也是连带的或者是偶然发的,继续观察看看
浙公网安备 33010602011771号