大部分情况下,线程池的运行情况对于使用者来说是个黑盒。
运行情况不可知,会导致生产出现事故问题排查困难,以及线程池参数难以定义
文章围绕线程池监控展开,讨论线程池如何监控、监控的指标以及监控数据的存储展示。
1. 如何监控运行数据
设想一下,如果想监控线程池的运行数据,你会怎么操作?
这里提供两种常规思路:
-
线程池运行时埋点,每一次运行任务都进行统计;
-
定时获取线程池的运行数据。
这里我推荐第二种。因为线程池的监控 API 会通过获取主锁来控制结果的相对准确性,性能相对较差,后面会详细说明。
为什么叫相对准确?
因为任务和线程的状态在计算过程中可能会动态变化,只能给到一个近似值,保证不了绝对准确。
模拟下定时采集线程池运行时数据的代码:
private ScheduledThreadPoolExecutor collectVesselExecutor;
String collectVesselTaskName = "client.scheduled.collect.data";
collectVesselExecutor = new ScheduledThreadPoolExecutor(
new Integer(1),
ThreadFactoryBuilder.builder().daemon(true).prefix(collectVesselTaskName).build()
);
// 延迟 initialDelay 后循环调用. scheduleWithFixedDelay 每次执行时间为上一次任务结束时, 向后推一个时间间隔
collectVesselExecutor.scheduleWithFixedDelay(
() -> runTimeGatherTask(),
properties.getInitialDelay(),
properties.getCollectInterval(),
TimeUnit.MILLISECONDS
);
一般线程池分为两种方式创建,Spring Bean 和非 Spring Bean,假设创建的线程池是 Spring 管理的。
我们只需要在 Spring 容器启动成功后,延迟一段时间后开始采集运行数据就 OK 了。
不论线程池是否由 Spring 管理,采集的方式大致相同。一种从 Spring 容器取,一种是创建好线程池后放到一个自定义容器。
2. 监控的指标有哪些?