关键词:
前言
在我们开发过程中,无法避免的会出现所谓的垃圾代码,导致服务器的CPU一直处于100%。但我们应用已经上线,导致服务器CPU居高,但又不知道哪边出现的问题,我们应该怎么去找出哪边的代码出现问题呢?今天老顾就介绍几种工具去快速定位。
演示代码
我们先来编写一下代码,新建springboot的maven项目,创建web服务,引入SpringBoot内置web容器,pom.xml关键引用jar包如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
创建service:TestWhile
创建Controller:TestWhile
配置文件application.properties
server.port=80
server.servlet.context-path=/api
打包项目,上传测试服务器
java -jar demo-0.0.1-SNAPSHOT.jar &
打开浏览器,访问死循环方法
打开浏览器,地址栏输入http://xxxx/api/user/testWhile?size=2
返回“Hello 程序执行完毕”,说明调用成功。(开启了2个死循环)
到此问题代码,已经在服务器上面跑了。我们发现服务器报警,于是去线上排查。
原生方法
此方法无需额外安装工具,在没法连接互联网的情况下使用此方法排查效果较好。
top、printf都是Linux原生命令,jstack、jstat是jdk自带命令工具。
很多功能强大的Linux和java诊断工具也是以top、jstack、jstat为基础命令做的封装。
注意:jstack、jstat等命令需要jdk完整安装,linux自带的openJdk一般无此工具,可以在java的bin目录下查看是否有这些命令。
找到最耗CPU的进程
命令:top –c,显示进程运行信息列表
实例:top -c。
交互1:按1,数字1,显示多核CPU信息。
交互2:键入P (大写p),进程按照CPU使用率排序
我们看出了双核CPU使用率已经达到100%。
而第一个进程PID是373的就是我们要找的罪魁祸首了;可以看到进程最后一列,COMMAND注释的进程名:“java -jar demo-0.0.1-SNAPSHOT.jar”。
找到最耗CPU的线程
命令:top -H -p 【PID】,显示一个进程的线程运行信息列表
实例:top -Hp 373 ,如下图所示,可以看到多个高耗CPU使用率的线程
转换线程PID为16进制
命令:printf “%x ” 【线程pid】,转换多个线程数字为十六进制,第4步使用时前面加0x。
实例:printf ‘%x ‘ 406 405 375 376,得到结果196、195、177、178;如下图所示:
查看堆栈,定位线程
命令:jstack 【进程PID】| grep 【线程转换后十六进制】-A10 , 使用jstack获取进程PID堆栈,利用grep定位线程id,打印后续10行信息。
实例:jstack 373 | grep ‘0x196‘ -A10,如下图所示:
我们通过查看堆栈信息,发现了问题是TestWhile.whileTrue引起的;
而且发现有2个GC线程,看上图中的“GC task thread#0 (ParallelGC)”,代表垃圾回收线程,该线程会负责进行垃圾回收
存储堆栈,批量查看
查看堆栈信息,我们也可以换个方法查看,可以先将jstack堆栈信息存储起来。
命令:jstack 【进程PID】> 【文件】
实例:jstack 373 > demo.dump,存储373进程的堆栈信息。
再使用cat + grep查找看看后面几个高CPU线程的堆栈信息。
实例:cat -n demo.dump | grep -A10 ‘0x196‘,如下图所示:
可以看到线程0x196【线程196】产生堆栈信息,直指方法whileTrue。
GC查看
我们看到上图中有4个线程中的2个线程没有看到java代码,而是GC task thread#0 (ParallelGC),这个是GC垃圾回收的线程,是不是死循环导致了GC太频繁,导致CPU使用率居高不下呢?
我们使用jstat看下jvm的GC信息看看。
命令:jstat -gcutil 【进程PID】【毫秒】【打印次数】
实例:jstat -gcutil 373 2000 5,查看373进程的GC信息,每2秒打印一次,共打印5次,如下图所示:
S0:幸存1区当前使用比例
S1:幸存2区当前使用比例
E:伊甸园区使用比例
O:老年代使用比例
M:元数据区使用比例
CCS:压缩使用比例
YGC:年轻代垃圾回收次数
FGC:老年代垃圾回收次数
FGCT:老年代垃圾回收消耗时间
GCT:垃圾回收消耗总时间
上面的原生方法查找要遵循一定的步骤,相对有些麻烦点,有没有比较简单的方法呢?往下看
Arthas(阿尔萨斯)
Arthas(阿尔萨斯)是阿里巴巴开源出来的一个针对 java 的线上诊断工具,功能非常强大。Arthas 支持JDK 6+,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。我们来看看
下载Arthas
使用arthas-boot(推荐)
下载arthas-boot.jar,然后用java -jar的方式启动:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar java -jar arthas-boot.jar
按1进入java进程,此时java进程PID已经变成373
进入阿尔萨斯完成,如下图,可以看到登录路径已经变成了[arthas@17376]$,可以输入dashboard,进入监控页面了。
监控查看
已经进入Arthas操作界面,输入dashboard,回车后将看到线程及堆栈信息,如图所示,arthas已经将cpu高使用率的线程给安排上了。
上面我们就看到有2个线程居高不下,还有GC的数量和耗时。
thread【ID】查看线程
ctrl + c 退出dashboard界面,输入thread 32查看线程信息,如下图所示:
可以看到是TestWhile类中的whileTrue方法中的put方法导致cpu使用率升高。
问题一下子就出来了,Arthas功能不单单止于此,可以直接反编译,看看代码。
jad反编译
使用Arthas自带的反编译方法jad,输入命令:
jad com.rainbow.demo.service.TestWhile
可以反编译java的class查看问题函数的具体代码,如下图所示:
退出arthas
最后,既然问题已经找到,那就退出Arthas吧。输入命令:quit
Arthas的功能是非常强大的,这里就简单介绍,下一次老顾用专门的文章介绍
老顾在介绍一个更简单的一个脚本,立刻发现问题所在
show-busy-java-threads
show-busy-java-threads.sh这个工具是useful-scripts工具集的其中一个工具。
show-busy-java-threads用于快速排查Java的CPU性能问题(top us值过高),自动查出运行的Java进程中消耗CPU多的线程,并打印出其线程栈,从而确定导致性能问题的方法调用。
注意:此工具的核心还是使用jdk的jstack方法,只是在其上做了封装展示。
# 下载到当前目录下
下载地址:https://github.com/oldratlee/useful-scripts/releases
在bin下面有很多工具,我们这次只要show-busy-java-threads.sh
上传show-busy-java-threads脚本到服务器
# 一定赋予执行权限
chmod +x show-busy-java-threads
直接运行
./show-busy-java-threads
如下图所示,找到了CPU使用率前5高的线程,查找非常迅速。
从前面两个线程可以看出,与使用原生工具(jstack)看到的一样。
其他命令
与Arthas一样,show-busy-java-threads也有一些其他很好用的增强命令:
show-busy-java-threads
从所有的 Java进程中找出最消耗CPU的线程(缺省5个),打印出其线程栈。
show-busy-java-threads -c 3
-c 3:3为n,指定显示最耗cpu使用率前3的线程。
show-busy-java-threads -c 3 -p 17376
展示进程17376耗费CPU组多的3个线程;
-p 17376 :17376为进程PID,-p参数指定进程PID。
show-busy-java-threads -s 【指定jstack命令的全路径】
对于sudo方式的运行,JAVA_HOME环境变量不能传递给root,
而root用户往往没有配置JAVA_HOME且不方便配置,
显式指定jstack命令的路径就反而显得更方便了
show-busy-java-threads -a yao.log
将输出结果导入到指定文件yao.log中
show-busy-java-threads 3 5
每5秒执行一次,一共执行3次; 缺省执行一次,缺省间隔是3秒
总结
今天老顾介绍了3中方法排查服务器CPU负载过高的情况,主要流程是
1、查看CPU负载过高进程。
2、查看进程中负载高的线程。
3、获取进程中的堆栈信息。
4、获取堆栈中对应的线程信息,找到里面的问题方法。
在排查过程中我们不只使用了原生工具,还使用了增强工具Arthas与show-busy-java-threads,大大简化了我们排查的步骤。
其实增强工具无非就是在原生方法上面封装了而已,有很多这种工具都是在原生方法中封装而成。
阿里java诊断工具arthas-排查线上环境内存使用过大线程cpu使用率高问题(代码片段)
一、arthas上篇文章对arthas的安装以及指令做了展示,可以感觉出arthas提供的指令还是挺多的,上篇文章没有对指令进行过多的演示,目的是大家在学习arthas后,就可以在上篇文章或者官方文档中统一查找定位使用... 查看详情
阿里开源的那个牛x的问题排查工具——arthas,推出idea插件了!|文末福利(代码片段)
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!|文末福利△Hollis,一个对Coding有着独特追求的人△这是Hollis的第264篇原创分享作者l汪小哥来源lHollis(ID:hollischuang)Arthas对于很多Java开发者来说,已经不可分割了,... 查看详情
jvm线上故障排查基本操作(转)
...位问题所在,然后分析问题原因,再然后解决问题,最后进行总结,防止下次再次出现。 本文的排查环境是Linux。CPU飚高问题:线上CPU飚高问题大家应该都遇到过,那么如何定 查看详情
java生产环境调试问题排查神器arthas(阿里中台开源的)
java生产环境调试、问题排查神器arthas(阿里出的)Arthas是一款线上监控诊断产品,通过全局视角实时查看应用load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、... 查看详情
jvm线上故障排查基本操作--cpu飙高
...到CPU消耗最高的线程ID,并记住线程ID.通过JDK提供的jstack工具dump线程堆栈信息到指定文件中。具体命令:jstack-l[进程ID]>jstack.log。由于刚刚的线程ID是十进制的,而堆栈信息中的线程ID是16进制的,因此我们需要将10进制的转换... 查看详情
线上服务cpu100%问题快速定位实战--转
...的功底。 58到家架构部,运维部,58速运技术部联合进行了一次线上服务CPU问题排查实战演练,同学们反馈有收获,特将实战演练的试题和答案公布出来,希望对大家也有帮助。 题目某服务器上部署了若干tomc 查看详情
阿里开源那个牛哄哄问题排查工具竟然不会用?最佳实践来了!(代码片段)
阿里开源那个牛哄哄问题排查工具竟然不会用?最佳实践来了!△Hollis,一个对Coding有着独特追求的人△这是Hollis的第291篇原创分享作者l汪吉来源lHollis(ID:hollischuang)入门步骤安装https://arthas.gitee.io/install-detail.html上述命令会下... 查看详情
java应用线上问题排查思路
CPU利用率飙升1、定位cpu利用率最高的进程top2、定位使用cpu最高的线程top-Hppid3、线程id转化为16进制printf‘0x%x‘tid4、找到线程堆栈jstackpid|greptid发现使用cpu最高的是业务线程1、iowait解决方法:[1]:https://blog.csdn.net/lonyness/article/detai... 查看详情
线上性能问题初步排查方法
...示启动当前进程的命令,在Java进程这一行里可以看到CPU利用率是 查看详情
利用阿里云arms排查java大量文件处理场景堆外内存溢出(线上jvm排障之八)
背景:线上一个项目线上3节点POD,内存一点点爬升最后100%打满,然后就会触发K8s的驱逐机制,重启。然后内存又是一点点的爬升周而复始,系统完全不可用。先看线上系统POD上的内存CPU使用情形,如下图所示: 线上内存几... 查看详情
阿里云k8s容器pod中java进程cpu占比100%排查(线上jvm排查之一)
...点,其中有一个节点重启之后CPU占比100%。系统整体基于阿里云K8s部署,接入了阿里云的ARMS监控。1.发现CPU占比100%的节点 从上图看出这个pod只有1核,实际上这个pod是部署在node上,node是32核心的。是设置了pod的limit=1。查看CPU... 查看详情
阿里云k8s容器pod中java进程cpu占比100%排查(线上jvm排查之一)
...点,其中有一个节点重启之后CPU占比100%。系统整体基于阿里云K8s部署,接入了阿里云的ARMS监控。1.发现CPU占比100%的节点 从上图看出这个pod只有1核,实际上这个pod是部署在node上,node是32核心的。是设置了pod的limit=1。查看CPU... 查看详情
java线上故障排查
...时候尽量四个方面依次排查一遍。同时例如jstack、jmap等工具也是不囿于一个方面的问题的,基本上出问题就是df、free、top三连,然后依次jstack、jmap伺候,具体问题具体分析。 内存泄漏、内存溢出、CPU飙升三者之间... 查看详情
谈谈线上cpu100%排查套路(代码片段)
...接下来呢根据PID查出消耗Cpu最高的线程号这里用到微软的工具ProcessExplorerv16.22,地址如下https://docs.microsoft.com/zh-cn/sysinternals/downloads/process-explorer如图所示发现最耗Cpu的线程的TID为6616这是十进制的数据, 查看详情
记一次线上机器cpu飙高的排查过程
...角度来讲,其实大部分性能问题都是垃圾回收的锅。然后利用ps查看到的进程pid找cpu最高线程然后拿着线程tid在jstack找,结果在里面找不到,然后上网查JAVA线程无法在jstack里找到的原因以上大概意思是没找到线程的跟踪栈有三种... 查看详情
利用阿里云arms排查java大量文件处理场景堆外内存溢出(线上jvm排障之八)
背景:线上一个项目线上3节点POD,内存一点点爬升最后100%打满,然后就会触发K8s的驱逐机制,重启。然后内存又是一点点的爬升周而复始,系统完全不可用。先看线上系统POD上的内存CPU使用情形,如下图所示: 线上内存几... 查看详情
记一次线上cpu100%排查过程(代码片段)
引言不知道在大家面试中,有没有遇到这个问题:生产服务器上部署了几个java程序,突然出现了CPU100%的异常告警,你如何定位出问题呢?这个问题分为两版回答!高调版对不起,我是做研发的,这个问题在生产上是不... 查看详情
线上故障排查全套路盘点,运维一片就够
...时候尽量四个方面依次排查一遍。同时例如jstack、jmap等工具也是不囿于一个方面的问题的,基本上出问题就是df、free、top三连,然后依次jstack、jmap伺候,具体问题具体分析即可。 CPU 一般来讲我们首先会排 查看详情