JIT逆优化引发的Java服务瞬时抖动 问题排查&解决方案

文章讲述了Java服务在高QPS下遇到的抖动问题,通过前期排查和实验失败后,作者引入JavaFlightRecorder(JFR)来记录服务异常时期的详细指标,发现抖动与JIT逆优化有关。最终通过graal编译器和修改OpenJDK源码解决了问题,强调了可观测性和底层技术理解的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、背景

二、前期排查(失败)

三、使用神器JFR

四、学习JIT&思考解决方案

五、最终的解决方案

六、总结

一、背景

我们有一个QPS较高、机器数较多的Java服务;该服务的TP9999一般为几十ms,但偶尔会突然飙升至数秒,并会在几秒内自动恢复(抖动期间伴随着CPU占用100%、线程池大量扩容)。抖动大都集中在新代码上线后的前几天,会随着时间拉长逐渐减少。

二、前期排查(失败)

前期未排查到问题根因,也不知道如何去定位根因;只好从现象出发(CPU占用100% 和 线程池大量扩容),尝试通过解决表面现象,从而避免服务抖动。具体做了以下工作进行测试验证:

工作项 预期 结果
固定线程池线程数 避免因线程创建销毁、线程上下文切换产生的CPU开销 抖动时的TP峰值降低,但抖动仍存在
监控线程CPU占用的shell脚本 捕获异常时刻到CPU占用高的线程 捕获到的线程比较多,有业务代码线程、C2编译器线程、GC线程...
JIT调优(提高编译阈值、减少C2线程数...) 降低CPU占用 效果不明显
试用JDK21的虚拟线程 避免因线程创建销毁、线程上下文切换产生的CPU开销 使用虚拟线程后,抖动时的TP峰值降低,但抖动仍存在
试用JDK21的结构化并发 避免部分业务线程查存储失败后,其他线程还在运行、持续占用CPU 结构化并发也是基于虚拟线程的,效果和虚拟线程类似
试用分代ZGC 降低GC线程的CPU占用 无效

这时候我们发现针对表面的现象可以做的猜想实在是太多了,对应的实验也太多了,很多时候也很难通过实验去完全地证伪这些猜想。

基于“抖动大都集中在新代码上线后的前几天”的现象,服务冷启动和JIT编译确实有很大的嫌疑,但是JIT编译真的会持续这么多天吗?我们并不能理解,开启了J

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值