原文详见https://ricstudio.top/archives/java-online-question-probe

不管出现任何问题,优先级最高的永远是恢复服务,保留下当时的异常信息(内存dump、线程dump、gc log等等,在紧急情况下甚至可以不用保留,等到事后去复现),等服务正常,再去复盘问题

常见问题: Cpu 利用率高\飙升

常见原因:

  • 频繁Gc
  • 死循环,线程阻塞 ,io wait…etc

定位问题

传统方法top

针对的是Java进程启动开始到现在的cpu占比情况

  1. top 命令查看系统进程监控, hp按照线程排序 hm根据内存排序
  2. top -Hp pid 定位Cpu最好的线程

image.png

  1. printf ‘0x%x’ tid 线程 id 转化 16 进制
  2. jstack pid | grep tid 找到线程堆栈
    1. jstack 12816 | grep 0x3211 -A 30
    image.png

    top 命令显示的指示符的含义

    | 指示符 | 含义 | | —- | —- | | PID | 进程id | | USER | 进程所有者 | | PR | 进程优先级 | | NI | nice值。负值表示高优先级,正值表示低优先级 | | VIRT | 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES | | RES | 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA | | SHR | 共享内存大小,单位kb | | S | 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程 | | %CPU | 上次更新到现在的CPU时间占用百分比 | | %MEM | 进程使用的物理内存百分比 | | TIME+ | 进程使用的CPU时间总计,单位1/100秒 | | COMMAND | 进程名称(命令名/命令行) |

简化top的工具

show-busy-java-threads,但我没用过

阿里云的arthas

arthas这种是一段采样间隔内,当前JVM里各个线程所占用的cpu时间占总cpu时间的百分比。
如果没有安装,可以线上安装.

  1. curl -O https://arthas.gitee.io/arthas-boot.jar # 下载

image.png

  • dashboard :系统实时数据面板, 可查看线程,内存,gc 等信息
  • thread :查看当前线程信息,查看线程的堆栈,如查看最繁忙的前 n 线程
  • getstatic:获取静态属性值,如 getstatic className attrName 可用于查看线上开关真实值
  • sc:查看 jvm 已加载类信息,可用于排查 jar 包冲突
  • sm:查看 jvm 已加载类的方法信息
  • jad:反编译 jvm 加载类信息,排查代码逻辑没执行原因
  • logger:查看logger信息,更新logger level
  • watch:观测方法执行数据,包含出参、入参、异常等
  • trace:方法内部调用时长,并输出每个节点的耗时,用于性能分析
  • tt:用于记录方法,并做回放

    常见现象

    发现cpu最高 的是Gc线程

    1. GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00007fd99001f800 nid=0x779 runnable
    2. GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00007fd990021800 nid=0x77a runnable
    3. GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00007fd990023000 nid=0x77b runnable
    4. GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00007fd990025000 nid=0x77c runnab

    排查方法:

  • 方法a : 查看gc 日志 (需要记得开启)

  • 方法b : jstat -gcutil 进程号 统计间隔毫秒 统计次数(缺省代表一致统计
  • 方法c : 如果所在公司有对应用进行监控的组件当然更方便(比如Prometheus + Grafana)

获取到gc日志之后,可以上传到GC easy帮助分析,得到可视化的图表分析结果。
image.png

发现cpu最高的是业务线程

  • 等待内核态锁,如 synchronized
    • jstack -l pid | grep BLOCKED 查看阻塞态线程堆栈
    • dump 线程栈,分析线程持锁情况。
    • arthas提供了thread -b,可以找出当前阻塞其他线程的线程。针对 synchronized 情况
    • 查询是否有代码死锁: jstack –l pid | grep -i –E ‘BLOCKED | deadlock

常见问题恢复

image.png