1. 问题起因
某个项目上线了几天后,突然项目的线程数彪升。触发了报警。
查看Falcon平台,发现在9:40的时候,项目的线程数突然彪升。
2. 排查流程
登录对应服务器:
- 使用
top
命令查询PID(57021),且发现CPU使用率并没有上升; - 使用
jstat -gcutil 57021 250 100
打印GC情况发现GC情况也比较正常,不是GC线程的问题。 - 使用
jstack 57021 >test.log
将项目的线程堆栈信息打印到文件中。
发现test.log
文件存在很多下图所示的线程信息:
- 使用
jstack -l 57021 | grep cluster | wc -l
命令进行统计,发现项目中cluster
线程数800多个。
由此推测,应该是com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.waitForSignalOrTimeout(DefaultServerMonitor.java:226)
位置的代码原因。
3. 查询源码
DefaultServerMonitor推测,可能是一个Mongo监控检查的功能。
而此线程启动是创建DefaultServer时。
创建MongoClient对象时会创建DefaultServer。
在网上百度了下,没有人反应mongodb项目运行一段时间后monitorThread线程数飙升。而根据源码发现,每一次去创建MongoClient对象时,都会去开启monitorThread线程。所以推测:项目在启动后,有动态创建MongoClient对象的动作。
4. 问题定位
因为我们有一个接口,需要根据用户上送的参数去动态的切换mongo库。而切换库时,每次都是创建MongoClient对象(不是从缓存中获取)。且创建MongoClient对象都会启动monitorThread线程(且不会被回收)。所以当大量访问某个接口时,会使得项目的线程数彪升。