每天 9 点报表任务启动后,订单接口 P99 从 300ms 涨到 12 秒,两边用的是同一个 32 线程的池,活跃线程全被报表占着。日志里能对上时间点,这种反而好排。
离线任务和在线接口共享线程资源,没有做隔离。报表一批几十个任务进来,把池占满,在线请求只能排在后面。这一点先确认清楚,后面就不用反复试。
ThreadPoolExecutor orderPool = new ThreadPoolExecutor(24, 48, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000)); ThreadPoolExecutor reportPool = new ThreadPoolExecutor(8, 8, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(200));
围绕「线程池隔离」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
别只看报错的最后一行,往上看几行,真正的起因通常在上面。
处理上按这个顺序:按业务拆池 订单一个池 报表一个池 各自设上限;报表池降低优先级 CPU 也让出一些;给在线池留最小可用线程 拒绝离线任务抢占;用压测同时打两类请求 看两边 P99 是否互不影响。
结果对不对很好判断,报表运行时订单 P99 保持在 500ms 内,报表自身耗时没有明显变长。
