已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
【背景】
我负责一个支付网关服务:Spring Boot 3.2 + JDK 17(G1,-Xmx4g,tiered compilation 开启,默认参数)+ MySQL 8 + Redis 7,K8s 滚动发布,单副本 4C8G,QPS 约 600。每次发布后我都能稳定复现一个现象:新 Pod 就绪后的前 2–4 分钟,核心扣款接口 P99 从日常的 30ms 升到 90–140ms,随后自行回落到基线;P50 基本不受影响。CPU 利用率在这段窗口里反而偏高(从 25% 升到 45% 左右),GC 日志没有 Full GC、Young GC 停顿也都在 10ms 以内,连接池没打满、慢查询没有——所以"直觉"指向 JIT 还没把热点路径编译成 C2 代码。
【现象与卡点】
-XX:+PrintCompilation 观察:发布后前 2 分钟日志里 compiler=1(C1)刷屏,compiler=2(C2)的编译记录集中在 1.5–3 分钟才密集出现——C2 编译完成的时刻,和 P99 回落的时刻肉眼上是对得上的,但这只是"看着像",我没法给出一个能说服复盘会、能写进 SOP 的量化证据;【已尝试】
-XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation 抓了编译日志,但 log.xml 很大,我不知道该按哪个字段(osr / method / 时间戳)去对齐 P99 曲线;jstat -gcutil 和 async-profiler 的 wall 模式采样,但采样粒度是秒级,发布后这 2–4 分钟里 P99 的毛刺在采样点上被摊平了,看不出和编译事件的因果关系;【期望得到的答案形态】
LogCompilation 与 P99、用 async-profiler 的细粒度模式或 -XX:+UnlockDiagnosticVMOptions 的相关开关),并给出一个能排除"CPU 抢占"和"懒初始化"干扰的对照实验设计;-XX:+TieredStopAtLevel、发布前 warmup 流量(金丝雀/影子请求)该打多久、-XX:+AlwaysPreTouch 之类该不该开,各自对这段窗口能缩短多少、有没有副作用(内存、启动时长);