V9 某项目 cpu飙高解决方案
由 he shancai 在 将近 3 年 之前添加
一、中间件版本:v9企业版
二、jdk版本:bisheng-jdk-8u282-linux-aarch64.tar.gz
三、问题现象:
1、CPU利用率处于二级阈值区域:90.0%,cpu飙高持续时间短,偶发导致cpu经常报警,极其不稳定
2、系统使用正常,功能正常,cpu飙高进行报警
四、排查工具以及手段:
1、通过top 查看,查看那些进程占比最高,top 前三的进程
2、Arthas 工具在cpu飙高时抓取cpu飙高的java中的线程信息
五、排查过程及其解决方案:
1、问题一:中间件seesion持久化占用cpu较高资源
解决优化:
尝试一:
调整session相关参数
SessionCreationPolicyOnMax:参数表示当内存中的活动 session 数目大于 MaxSessionsInCache 所设定的值时,应用服务器在创建新 session 时采取何种策略,
可选的值为: Override、 NotAllow、 ExpireOld 及 SwapOutOld,默认值为 SwapOutOld。各取值含义说明如下:
(1)Override:忽略最大限制,继续创建新 Session,由后台线程负责清除多余的session,清除多余 session 的策略,由辅助参数 BackgroundPolicyOfOverrideOnMax 指定;
(2)NotAllow:不允许超过最大限制,如超过,直接抛异常;
(3)ExpireOld:如超过最大限制,先废弃掉多余的旧 session,再创建新的;
(4)SwapOutOld:如超过最大限制,先把内存中多余的旧 session 交换到持久存储SessionStore 中,再创建新的。
BackgroundPolicyOfOverrideOnMax:
该属性为 SessionCreationPolicyOnMax 的辅助属性,
当 SessionCreationPolicyOnMax 的取值为 Override 时,需要设置该属性。
其可选的取值为: ExpireOld 及 SwapOutOld,默认值为 SwapOutOld,取值的含义同 SessionCreationPolicyOnMax 中的解释。
改为一下参数:
<SERVICE
CLASS="com.apusic.web.session.SessionService"
>
<ATTRIBUTE NAME="DefaultSessionTimeout" VALUE="36000"/>
<ATTRIBUTE NAME="MaxSessionsInCache" VALUE="10240"/>
<ATTRIBUTE NAME="SessionInvalidateCheckInterval" VALUE="60"/>
<ATTRIBUTE NAME="SessionCreationPolicyOnMax" VALUE="Override"/>
<ATTRIBUTE NAME="BackgroundPolicyOfOverrideOnMax" VALUE="ExpireOld"/>
<ATTRIBUTE NAME="Distributable" VALUE="False"/>
<ATTRIBUTE NAME="Replicable" VALUE="False"/>
<ATTRIBUTE NAME="SessionStick" VALUE="True"/>
<ATTRIBUTE NAME="PersisteSession" VALUE="False"/>
<ATTRIBUTE NAME="DestorySessionOnApplicationStop" VALUE="True"/>
</SERVICE>
效果:session进程占用cpu得到优化,但是还是会偶发飙高
尝试二:cpu飙高时,发下中间件session相关线程还是会有占用cpu高的情况
优化措施:session的失效时间调整为5分钟
/AAS/domains/mydomain/config/web.xml
优化效果:经过两次优化后,session线程占用高的情况得到明显改善,排除因为session导致整体cpu飙高的情况。
2、问题二:优化中间件session相关后,cpu还是不稳定,整体没得到根本改善
通过Arthas分析,得到应用方存在导致cpu飙高的线程,如md5加解密相关进程,initEcode相关进程
解决:应用厂商进行优化后,得到改善,系统运行后,cpu依然在飙高
3、问题三:jVM内置线程忙,C2 CompilerThread,始终占用较高cpu
关于C2 CompilerThread相关机制可阅读该文章:https://tech.meituan.com/2020/10/22/java-jit-practice-in-meituan.html
补充知识:
JIT编译线程,用于将java字节码编译成本地代码。
字节码一般只需要编译一次,编译完后会存放在jvm的cache中。
因此,这些线程忙一般常见于java进程启动后的第一次压测的时候,编译完后这些线程就不应该占cpu了。
解决办法就是先预压测几次,然后再正式压测。
如果发现压测过程中还是有这些线程占用cpu的情况,则有可能是cache不够大,需要通过-XX:ReservedCodeCacheSize调大。
推断原因:CodeCache 默认为128m,缓存不足,jvm编译线程忙于将字节码翻译为机器码,无法复用前期缓存
解决:添加jvm参数进行优化
-XX:InitialCodeCacheSize=128m 初始化缓存大小
-XX:ReservedCodeCacheSize=512m 最大缓存大小
效果:添加参数后,cpu飙高得到根本改善,从而确定主要问题为C2 CompilerThread引起。