一、通过jstack排查
1.通过top命令找到cpu占用高的应用程序进程
top
2.通过top -Hp pid查看该应用中占用CPU高的线程
top -Hp 5649
下图中是线程id
3.通过printf "%x\n" [线程id] 将线程高的线程号转为十六进制。
4.通过jstack过滤该十六进制的关键信息。jstack [进程号]|grep -A 10 [线程的16进制]
如下所示,定位到问题代码行
[root@VM-100-3-centos ~]# printf "%x\n" 6887
1ae7
[root@VM-100-3-centos ~]# jstack 5649 | grep -A 10 1ae7
"http-nio-18001-exec-107" #126 daemon prio=5 os_prio=0 tid=0x00007f48ec069000 nid=0x1ae7 runnable [0x00007f493cba1000]
java.lang.Thread.State: RUNNABLE
at com.tony.edu.perf.PostmanApplication.memory(PostmanApplication.java:48)
at sun.reflect.GeneratedMethodAccessor30.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
[root@VM-100-3-centos ~]#
二、通过Arthus(阿尔萨斯)排查
jstack排查,因为占用高的线程可能很快执行完了,手动操作,不容易定位,所以通常使用封装好的脚本或者工具,比如阿里的Arthus(阿尔萨斯)
Artuhs 是阿里巴巴开源的 java 的诊断工具
Arthas 地址:https://github.com/alibaba/arthas
官方文档:arthas
下载地址:Releases · alibaba/arthas · GitHub
1、下载后解压
2、进入解压目录
3、执行 java -jar arthas-boot.jar,启动
wyl@WYLdeMacBook-Air arthas-packaging-3.7.2-bin % pwd
/Users/wyl/Downloads/arthas-packaging-3.7.2-bin
wyl@WYLdeMacBook-Air arthas-packaging-3.7.2-bin % java -jar arthas-boot.jar
[INFO] JAVA_HOME: /Library/Java/JavaVirtualMachines/jdk-17.jdk/Contents/Home
[INFO] arthas-boot version: 3.7.2
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
* [1]: 1827 sys_perf_01-0.0.1-SNAPSHOT.jar
[2]: 1748 jd-gui-1.6.6-min.jar
[3]: 1917 /Users/wyl/program/apache-jmeter-5.6.3/bin/ApacheJMeter.jar
4、要观察第哪个应用,输入哪个应用前面的序号。
如下示例,输入1
1
[INFO] arthas home: /Users/wyl/Downloads/arthas-packaging-3.7.2-bin
[INFO] Try to attach process 1827
Picked up JAVA_TOOL_OPTIONS:
[INFO] Attach process 1827 success.
[INFO] arthas-client connect 127.0.0.1 3658
,---. ,------. ,--------.,--. ,--. ,---. ,---.
/ O \ | .--. ''--. .--'| '--' | / O \ ' .-'
| .-. || '--'.' | | | .--. || .-. |`. `-.
| | | || |\ \ | | | | | || | | |.-' |
`--' `--'`--' '--' `--' `--' `--'`--' `--'`-----'
wiki https://arthas.aliyun.com/doc
tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
version 3.7.2
main_class org.springframework.boot.loader.JarLauncher
pid 1827
time 2024-02-29 09:28:09
5、dashboard,进入看板,看板会自动刷新
6、ctrl+c,退出看板,输入 thread 57,查看该线程的问题代码行
附录、CPU 占用高的测试代码
import io.swagger.annotations.Api;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@RestController
@Api("- )
public class PostmanApplication {
public static void main(String[] args) {
SpringApplication.run(com.tony.edu.perf.PostmanApplication.class, args);
}
@GetMapping({"/cpu"})
public ResponseEntity cpu() {
long count = 1L;
while (count < 10000000L) {
count++;
System.currentTimeMillis();
}
return ResponseEntity.ok(");
}
@GetMapping({"/memory"})
public ResponseEntity memory() throws InterruptedException {
long startTime = System.currentTimeMillis();
byte[] data = new byte[67108864];
Thread.sleep(10L);
return ResponseEntity.ok("+ data.length);
}
}
启动服务后,访问 http://host:port/cpu,及可以触发
## 场景1 JVM的内存配置太少
## 1. 设置 512MB
java -Xmx512m -jar sys_perf_01-0.0.1-SNAPSHOT.jar
## 2. 加大一倍内存 1200M
java -Xmx1200m -jar sys_perf_01-0.0.1-SNAPSHOT.jar
## 场景2 WEB服务器 提供的 线程数 过少
## 1. WEB服务器 提供的 线程数 过少
java -Xmx1200m -jar -Dserver.tomcat.max-threads=1 sys_perf_01-0.0.1-SNAPSHOT.jar
## 2.
java -Xmx1200m -jar -Dserver.tomcat.max-threads=100 sys_perf_01-0.0.1-SNAPSHOT.jar