摘要
TOP命令
进程出现cpu问题的时候,最常见的思路就是用top命令看一下是哪个线程导致的:
1 | 只看rpc进程的各线程cpu分布:(可以修改RpcServerModularStarter部分来锁定自己的进程) |
比如以上命令可以每隔2秒打印最高cpu占用的进程、线程到日志中。
占用内存、磁盘空间不大,可以长期开启,但是需要手动,比较麻烦。
容器云监控、诊断
公司有监控系统,自动开启了许多监控,我们可以看中间件的情况、cpu/线程池的历史情况:
信息安全因素这里略。
本质就是定时调用各个线程池的:
1 | java.util.concurrent.ThreadPoolExecutor.getTaskCount() |
async-profiler
配合jfr命令或者JDK Mission Control,可以定位常见的cpu,lock,alloc相关事件的问题。
参考之前写的: https://xiaoyue26.github.io/2022/03/25/2022-03/G1%E8%B0%83%E4%BC%98-%E5%A4%8D%E6%9D%82%E4%B8%9A%E5%8A%A1%E6%B2%BB%E7%90%86%E5%B0%8F%E8%AE%B0/
(-e参数可以指定cpu,lock,alloc,分别针对不同的jfr事件,可以生成.jfr文件)
参考:https://github.com/jvm-profiling-tools/async-profiler
jmc(JDK Mission Control)
: https://adoptium.net/jmc/
JFR监控
JFR: Java Flight Record (Java飞行记录)
JVM内置的黑匣子。jdk11中支持136个事件,
前面的async-profiler中生成的jfr只会记录其中少量一些cpu\lock\alloc相关的事件,所以优点生成的jfr文件会比较小。
缺点就是有些信息不够详细,也不够定制化。
JFR作为jvm内置的黑匣子,支持的事件非常细而全,目标是定位jvm所有问题:
(来自:https://bestsolution-at.github.io/jfr-doc/
,这个网站里还有各个event的简要信息)
使用流程:
1。定制jfc文件(配置需要打印的events);
2。用jfc采集jfc。
1.定制化event事件(生成jfc)
默认JAVA_HOME里的jfc开销和大小都太大(>100M/min),可以定制化开销较小的(仅选取关心的事件)。
jdk8-small.jfc
jdk11-small.jfc
default-jdk8.jfc
default-jdk11.jfc
2.采集事件(生成jfr)
1 | 开始监控: |
生成res.jfr文件以后,可以用JDK Mission Control
打开进行图形化的分析:
内存分配
可以按thread,class,方法聚合统计
锁
可以按class,address聚合统计;
如果cpu问题不是某几个线程cpu占用特别高导致的,一般就是”惊群效应”导致的。
也就是一大堆线程同时被唤醒(每个线程只占一点点cpu,但是累积起来就很多)。
而这种情况往往就是这些线程同时在等待某个锁,所以cpu问题看锁的统计是很有用的。
code dump
可以查看挂掉时候的调用栈信息:
总结
cpu问题可以分为两类:
1。某几个线程占大头:用top监控,可以配合jstack找出即可;
可以参考http://xiaoyue26.github.io/2022/11/21/2022-11/cpu%E6%AF%9B%E5%88%BA%E9%97%AE%E9%A2%98%E9%80%9A%E7%94%A8%E4%BC%98%E5%8C%96%E6%80%9D%E8%B7%AF/
2。没有特别高占用的线程,每个都占很少(比如3%)累积起来很多造成突刺:
惊群效应;可以找会阻塞住很多线程的方向:classLoader/jit/锁监控。