已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
【背景】 我们一个订单查询服务切到了 JDK 21 虚拟线程(JDK 21.0.3 / Spring Boot 3.2.5 / Tomcat 10.1),Tomcat 沿用平台模板 maxThreads=200、async.max-threads=40。单请求链路:Tomcat → 并行调「下游 HTTP 服务(Apache HttpClient 5,maxConnections=100)+ MySQL 8.0(HikariCP,maximumPoolSize=50)」。
【现象】 压测时 QPS 在 ~1300 出现硬平台:再往上 P99 从 200ms 直接跳到 3.5s 且不回来。但诡异的是——HikariCP 的 pending 始终为 0、active 从未到 50;而 HttpClient 的 leased 数稳定钉在 100(打满)。CPU 只用了 30%,jstack 里没有任何平台线程 BLOCKED,全是虚拟线程在 WAITING。
【已尝试的排查与结果】
【困惑与期望答案】 虚拟线程下,Tomcat 的 maxThreads 到底还约束什么?如果它形同虚设,那「单 Pod 容量上限」的真实决定因素是不是就是「所有下游连接池 max 之和」?如果是,那多下游场景(HTTP + DB + 还要加 Redis)下,各池 maxConnections 应该按什么公式对齐(Little's Law 里的 L 用哪个 R?),有没有人在线上做过「按下游池对齐容量」的定量实践?
另外:虚拟线程模式下,「carrier 池排队」和「下游池排队」在监控上怎么区分?JFR 里看哪个事件才能提前发现「QPS 即将到平台」?