服务端性能问题排查及优化---CPU高问题分析
邻近双11又开始另一轮的性能测试,陆续给大家奉上性能测试系列篇,从性能测试理论、性能测试案例高延迟(响应时间长)、CPU问题、内存问题、线上问题实战和性能测试书籍推荐等篇章。
上次篇《服务端性能测试指标及问题排查》,主要从理论的角度阐述性能测试指标和性能测试排除过程,从本篇开始讲高延迟的案例,主要从原因、问题分析、案例等进行分析和讲解。
- 1 -
概述
CPU高是常见的性能问题,但CPU高并不一定都是有问题,有可能你的业务就是CPU密集型的业务。
- 2 -
造成CPU问题的原因
| 代码Bug
可能性太多…
| 意外的死循环
| 线程数太多(线程数量是否比预期的异常的高)
大量的线程切换:线程数太多可能会导致频繁的线程上下文的切换,浪费CPU资源。
频繁创建销毁线程:线程的创建和销毁对系统的资源消耗比较大,如果一直在频繁的创建销毁临时线程导致资源占用,可能需要考虑下是否有其他更好的方案了。
线程池不正常的使用:比如Cache线程池初始化比较少、最小和最大的数量相差比较大、业务并发突然增大可能导致同时去创建线程。
| 频繁的FGC
导致频繁的FGC也会导致CPU高,比如由于JVM参数设置的不合理,年轻代和老年代的比例比例不合理导致频繁的FGC等。
| 不正常的使用某些类
比如Map的初始大小给的太小,而后续的使用中存的东西太多,可能会频繁的resize。
比如大数据量List的频繁查找,clone等。
- 3 -
CPU问题的分析过程
| 用到的工具和命令
jvisualvm
jstack,jstat,jmap,ps,top
| CPU高的几种情况
情况一:单核CPU使用率一直100%
| 分析方法
jstack pid > /tmp/jstack.txt
ps -mp pid -o THREAD,tid,time | awk '{printf $2" "$8"\n" }' | sort
printf "%x\n" tid
jstack pid | grep –A 20 tid
- 4 -
案例分析
| 案例介绍
| 分析过程
首先抓取客户端的线程堆栈,看看能否发现什么可以的地方。
分析堆栈发现线程有1000多,大部分为BLOCKED状态,ACTIVE状态基本看到的都是nio的,暂时没看到问题。
继续搜索本地package的以下名称,看看有没有在执行自己代码的地方,正好发现一些类似以下的信息。
Thread 1134: (state = IN_NATIVE)
- java.net.NetworkInterface.getAll() @bci=0 (Compiled frame; information may be imprecise)
- java.net.NetworkInterface.getNetworkInterfaces() @bci=0, line=334 (Compiled frame)
- com.alibaba.rocketmq.remoting.common.RemotingUtil.getLocalAddress() @bci=0, line=112 (Compiled frame)
- com.alibaba.rocketmq.client.ClientConfig.<init>() @bci=19, line=32 (Compiled frame)
- com.alibaba.rocketmq.client.producer.DefaultMQProducer.<init>(java.lang.String, com.alibaba.rocketmq.remoting.RPCHook) @bci=1, line=95 (Compiled frame)
- com.alibaba.rocketmq.client.producer.DefaultMQProducer.<init>(java.lang.String) @bci=3, line=86 (Compiled frame)
- ********************MQProducer.<init>(java.lang.String, java.lang.String) @bci=71, line=62 (Compiled frame)
- ********************.RocketMQ.sendMessage() @bci=76,line=119 (Compiled frame) // 119为源代码行号
- ********************.RocketMQ$1$1.safeRun() @bci=7, line=53 (Compiled frame)
- ********************.SafeRunnable.run() @bci=1, line=13 (Compiled frame)
- java.util.concurrent.ThreadPoolExecutor.runWorker(java.util.concurrent.ThreadPoolExecutor$Worker) @bci=95, line=1145 (Compiled frame)
- java.util.concurrent.ThreadPoolExecutor$Worker.run() @bci=5, line=615 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=745 (Interpreted frame)
public void sendMessage() {
try {
// 略…
Message msg = new Message("Performace", msgContent.getBytes("UTF-8"));
if (producer == null) {
producer = new MQProducer("Performace", "192.168.143.135:9876"); (1)
producer.start();
rst = producer.product(msg);
} else {
rst = producer.product(msg);
}
// 略…
} catch (Exception e) {
if (producer != null) {
producer.shutdown();
producer = null;
}
}
}