开放问答
线程池核心线程数拍脑袋设成 CPU×2,高峰期队列排队把 P99 拖垮,怎么科学估算容量?
该问题的正文、回答与评论。
提问者 程寒山 · 状态 open
线程池性能调优高并发JVM避坑清单
【背景】 我们有一个订单聚合服务(Java 17,Spring Boot 3,8C16G),核心逻辑要并行调用库存、价格、风控 3 个下游 RPC,每个下游 RT 大约 30~80ms,高峰期 QPS 约 2000。团队用「核心线程数 = CPU 核数 × 2 = 16」的土办法配置线程池,LinkedBlockingQueue 给到 1000,拒绝策略用 CallerRunsPolicy。
【现象】 平时一切正常,但大促压测时 P99 从 120ms 直接飙到 1.8s。线程 dump 里大量线程 RUNNABLE 卡在下游 socket 读,队列堆积到 800+,CallerRunsPolicy 又把任务丢回主线程,主线程自己也被下游拖住,最终触发上游熔断、雪崩。CPU 才用到 30%,显然不是算力瓶颈。
【已尝试的排查】
- 以为是下游慢,把超时从 500ms 收到 200ms,结果超时任务占满线程,雪崩反而更早;
- 把队列从 1000 改到 100,只是把「慢」换成「快速拒绝」,错误率飙升;
- 查了 CPU / 内存 / 网络全是绿的,慢日志指向下游 RT,但根因其实是线程池配比本身。
【期望得到的答案形态】 希望有人能给一套可复用的线程池容量估算方法或公式(要区分 IO 密集 vs CPU 密集,纳入下游 RT、目标 QPS、P99 预算),并说清队列长度和拒绝策略到底怎么选;最好带一个避坑清单或真实线上案例,别只给「按经验调」。
评论
暂无评论。