在某次工作的环境中发生接口调用一段时间之后出现 gateway timeout 504
问题,并随着大量的请求数量增大导致所有的接口都无法进行访问,第一时间怀疑是 tomcat 的请求连接数或线程池被压满,后来利用本篇提到的方法进行跟踪发现了问题;所以记录了如何使用 JVM 调优工具对这个问题进行定位并有效分析之后进行解决。
top
查看 进程ID;top -Hp 进程ID
查看线程数;pstack 进程ID
查看线程堆栈等信息。配置以下 JVM 参数变量方便远程客户端工具进行监控。
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=6001
-Dcom.sun.management.jmxremote.rmi.port=6001
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=172.16.1.10
注意:如果
java
程序跑在容器服务中(如:docker),则配置的端口号必须为6001
,否则将无法正常利用客户端工具进连接。
jvisualvm
工具我使用的是 Mac 电脑,所以对应的 JDK 目录及工具在 /Library/Java/JavaVirtualMachines/jdk1.8.0_77.jdk/Contents/Home/bin
之中,直接打开 jvisualvm
输入 IP 地址与端口号即可。
图中右下角状态说明。
打开调优工具之后,然后可以把服务进行重启,然后再查看目前 tomcat 所分配的线程数量(线程名格式:http-nio-8080-exec-1
),然后再手动调用接口或程序来进行跟踪线程数量来查找问题进行解决;在大量的刷新接口之后,明显发现线程数进行大量的增加,然后我们点击右边的 Thread Dump
按钮把堆栈信息打印出来,下面两种图是随便挑选的两个堆栈信息,从而方便问题的分析。
最后我们发现问题原来出现在连接池上面,导致大量的线程阻塞在获取连接处进行排队等待,所以我们加大了连接池的量最终解决了问题。