接口耗时从 50 毫秒涨到 400 毫秒,业务方法里的日志显示只跑了 55 毫秒,剩下的时间不知道耗在哪。日志里能对上时间点,这种反而好排。

任务提交到线程池后排队的时间没有算进任何埋点,池里线程被慢任务占着,请求在队列里干等,业务代码看不到这段,接口耗时和日志耗时于是差出一大截。这一点先确认清楚,后面就不用反复试。

long s = System.nanoTime();
future.get();
log.info('queue={}ms', (start - s) / 1000000);
pool.getQueue().size();

「线程池排队耗时」改完先别急着全量,挑一台机器放半天,真有问题这段时间就能看出来。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。

别只看报错的最后一行,往上看几行,真正的起因通常在上面。同类问题如果隔一段时间又出现,多半是某个定时任务或重启流程把改动冲掉了。

处理上按这个顺序:在提交前和任务开始时各记一个时间戳;同时记录队列长度和活跃线程数;对排队时间单独设告警而不是只看总耗时。

结果对不对很好判断,排队耗时和接口总耗时能对上,扩容线程数后这段明显变短。

作者 9823189