问题定位参考文章:
阿里Java诊断工具 arthas - 排查线上环境内存使用过大、线程cpu使用率高问题_arthas排查内存高问题_小毕超的博客-CSDN博客
【死磕JVM】用Arthas排查JVM内存 真爽!我从小用到大_牧小农的博客-CSDN博客_arthas 分析内存
1、遇到的问题
每次发版部署服务,线上服务器的cpu飙高超过100%
2、排查思路
找到一次服务发版的时候,利用公司提供的线上故障排查工具,其实是阿里开源的Arthas进行排查
原因:
C2 Compiler线程 占用大量cpu
热点方法会使用C2编译
Jdk8 默认开启分层编译
0:解释代码
1:简单C1编译代码
2:受限的C1编译代码
3:完全C1编译代码
4:C2编译代码
多数方法第一次编译级别是3(当然所有方法都是从级别0开始),如果方法运行的足够频繁,它就会编译成级别4
增加启动参数,输出编译、内联、codeCache信息到文件,分析编译日志
-XX:+UnlockDiagnosticVMOptions -XX:+PrintCompilation -XX:+PrintInlining -XX:+PrintCodeCache -XX:+PrintCodeCacheOnCompilation -XX:+TraceClassLoading -XX:+LogCompilation -XX:LogFile=/usr/local/discount.log
解决方案
- 提高年轻代内存,stg 占比提高到30%(4G*0.3),服务启动cpu利用率未见明显降幅
- 提高堆内存,stg 测试提高到6g,cpu利用率几乎下降一半(prd是ecs,stg是k8s,需要在线上测试)
- 增加c2编译器cpu个数,服务启动cpu利用率未见明显降幅
- 不提高内存,为了避免预热期间对线上请求的影响,可在服务启动后自建流量,预热完成后接入真实流量
- 最直接有效的方法是“预热(warm up)”:可以使用Jmeter等压测工具模拟线上访问流量,让C2 Compiler预先将热点代码编译成机器码, 减少对正式环境流量的影响。
解决方案参考文章:
jstack: Java占用高CPU分析之- C2 Compiler Thread_xiuson@TencentWesure的博客-CSDN博客_c2 compilerthread C2 CompilerThread9 长时间占用CPU解决方案_幸福丶如此的博客-CSDN博客_c2 compilerthread
C2 CompilerThread11引起的CPU较高分析_shuaisunny的博客-CSDN博客_c2 compiler