系统很卡-CPU一直长期处于100%的状态
排查步骤
登录服务器,查看CPU占用最高的所在进程,执行
top -c
,发现是 java 程序导致CPU飚高;查看服务器日志,是否是因为请求量过大和机器性能不行,查看后不是这原因,于是进行下一步;
由于采用的是docker部署,所以宿主机查看 pid 无法定位具体问题,这里直接采用
arthas
定位到具体的问题;docker stats
查看容器CPU占用最高的,然后使用docker exec -it {容器id} /bin/bash 进入容器
;由于 docker 安装都是最小化镜像,没有jdk环境,只有jre运行环境,无法执行类似于
jps
命令,所以先临时在docker容器中安装个jdk,然后启动arthas
进行排查;安装jdk和启动arthas命令步骤如下:
复制
# 下载jdk wget https://mirrors.huaweicloud.com/java/jdk/8u202-b08/jdk-8u202-linux-x64.tar.gz # 解压 tar -zxvf jdk-8u202-linux-x64.tar.gz # 下载 arthas wget https://arthas.aliyun.com/arthas-boot.jar # 启动 arthas ./jdk-8u202-linux-x64/bin/java -jar arthas-boot.jar
执行
thead -n 3
查看cpu最忙的3个线程,记录下pid;继续执行
thead pid号
,定位到具体的代码,我这里的日志如下:复制
[arthas@1]$ thread 5781 "http-nio-8080-exec-211" Id=5781 RUNNABLE at java.util.regex.Pattern$CharProperty.match(Pattern.java:3778) at java.util.regex.Pattern$Branch.match(Pattern.java:4606) at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660) at java.util.regex.Pattern$Loop.match(Pattern.java:4787) at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719) at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570) at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779) at java.util.regex.Pattern$Branch.match(Pattern.java:4606) at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660) at java.util.regex.Pattern$Loop.match(Pattern.java:4787) at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719) at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570) at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779) at java.util.regex.Pattern$Branch.match(Pattern.java:4606) at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660) at java.util.regex.Pattern$Loop.match(Pattern.java:4787) at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719) at java.util.regex.Pattern$BranchConn.match(Pattern.java:4570) at java.util.regex.Pattern$CharProperty.match(Pattern.java:3779)
分析结果
根据排查的结果发现是因为正则匹配的时候循环浪费的资源,这个正则表达式代码只有在一个接口中做前置判断有用到,就快速定位到了是正则表达式的问题,查阅相关资料和询问ChatGPT后,大概确定问题就是因为正则表达式不规范导致循环进行失控模式,分析参考文章链接,感兴趣的可以点进去看下,最后采用修改正则表达式然后重新发布服务CPU使用恢复正常。
总结
在本次操作过程中,遇到了很多问题坑,很多参考文章都是基于linux的指令和借助jstack、jps命令来排查,然后也不是针对于容器内的java程序进行排查,并且容器对应的pid和宿主机对应的pid不是一回事,所以只有靠定位到具体容器,进入容器再进行排查,一般容器使用的基础镜像为了保证足够精简,所以常常命令也是太简单,所以需要临时安装一些环境,这里推荐给大家arthas这款工具确实能够大大减少针对java程序排查问题的复杂度。
最后还是要提醒多久爱,写正则表达式参考网上的很可能有问题,使用前还是多斟酌,以免出现类似的线上问题。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 xieaoao@qq.com QQ:1296454177