性能问题定位详记
性能问题定位史1:探针监听线程异常终止不会自恢复,但进程不受影响
前提准备
-
安装openjdk上去(自家的jdk命令不全)
可能会看见 paas 有 java,root 没 java 的情况,这是正常的因为 root 和普通用户用的环境变量来源不一样,我们要把新的 jdk 以 root 用户安装。
通过自带的工具进行分析
-
用 top 命令找到最耗时的进程id
eg:
PID 是 进程号1 %CPU 显示为 184
PID 是 进程号2 , %CPU 显示为 157 -
top -Hp <进程ID>:查找此进程内最消耗cpu的线程
top -Hp 进程号1
找到 4724,4725,4726,4727
-
printf “%x\n” <线程ID>:把线程id转成16进制,以便查找;
printf “%x\n” 4724 得到 1274
-
jstack <进程id> | grep -99 <16进制线程ID> : 打印jvm线程栈;
jstack 进程号1 | grep -99 1274 (这里的99是指打印99行)
-
jstack <进程id> > tt.tmp 把进程状态存到 tt.tmp 文件内。
-
vim tt.tmp:查看进程中的热点函数。
-
jmap -histo | head -n10
-
jmap -dump:file=<文件名>
-
jvisualvm在jdk 1.8更新过的版本或高版本不带,要自己下载独立版
-
如果提示找不到 jdk 去visualvm的安装路径下,找到这个文件夹 xxx\visualvm_205\etc,检查一下这个字段配置了吗 visualvm_jdkhome=“jdk的绝对路径\jdk1.8.0_202”
使用阿里的Arthas进行辅助分析
-
上传zip包上去
-
创建一个文件夹放这个zip包!(必须,不然会解压出一大堆)
-
执行 “unzip Arthas-xxxxxxxxx.zip” 进行解压
-
执行 “sh install-lcoal.sh” 进行安装
-
执行 “java -jar arthas-boot.jar”
ps: 一定要去 jdk 目录下的 bin 执行这个命令,也就是说执行如下语句
./java -jar /路径/arthas-boot.jar
执行后,控制台若提示
[ERROR] Start arthas failed, exception stack trace: com.sun.tools.attach.AttachNotSupportedException: Unable to open socket file: target process not responding or HotSpot VM not loaded
这个时候可以关注一下 top 命令看到对应想要分析的进程号的 user 和你当前使用的 user 是不是同一个 user。eg: 是否都是 root ? 进程号2,进程号1
执行 “su -l 用户名” 来切换用户 ps:如果切换完变成 -bash-x.x$ 这个很可能是正常切换了,只是说这个用户的 ui 界面展示和别的用户不一样。
-
dashboard 会实时刷新展示 ctrl+c 退出
-
“thread -n 要展示的线程的数目” 会按 cpu占用率以降序展示想要展示的线程情况。
-
进程号2的dashboard 看了一两眼没看见有BLOCKED的线程,但是进程号1的dashboard 有一瞬间出现了3个BLOCKED的线程
以上定位了半天,不过没有啥出彩的效果,最后是分析代码,删去了冗余代码,避免了一个 Map 类对象的创建,可能是这个 map 没被释放导致的,删除之后就恢复了,于是结单了。但这次分析性能问题的过程学到了不少工具的使用方法。
结束。
代码小技巧
-
多个 if-else 考虑使用策略模式优化,实际处理时我采用了 <key -> value> 的数据格式进行优化。
-
并发编程中最好不要用timer定时器 —— 该建议原因收获自内部代码检视。
1 时间精度不高,偏差很大
2 多线程并行处理定时任务时,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行
建议使用ScheduledExecutorService