4核16G的设备,正常load average不大于4,表示系统一直处在负载状态,程序有异常。
每日服务器性能邮件告警
4核16G的服务器,load率达到了 6.97, 6.70, 4.87.
信息总览:
CPU 内核:4核
CPU load率: 6.97, 6.70, 4.87
总内存:15.3 GiB 使用内存:4.7 GiB 剩余内存:10.600000000000001GiB
TOP前5:
PID %CPU %MEM VSZ RSS Name
2805176 59.9 6.3 7.6 GiB 986.2 MiB java
2901828 13.1 5.4 4.1 GiB 847.4 MiB java
3532650 4.5 4.7 3.9 GiB 740.9 MiB java
3769112 3.0 4.2 5.5 GiB 657.7 MiB java
1619371 0.7 1.3 6.6 GiB 204.8 MiB java
注意:CPU load率: 6.97, 6.70, 4.87。load的平均值通过3个时间间隔来展示,就是我们看到的1分钟、5分钟、15分钟,load值和cpu核数有关,单核cpu的load=1表示系统一直处在负载状态,但是4核cpu的load=1表示系统有75%的空闲。
load高可能的一些原因
系统load高通常都是由于某段发布的代码有bug或者引入某些第三方jar而又使用不合理导致的,因此注意首先区分load高,是由于cpu高导致的还是io高导致的,根据不同的场景采取不同定位问题的方式。
- 死循环或者不合理的大量循环操作,如果不是循环操作,按照现代cpu的处理速度来说处理一大段代码也就一会会儿的事,基本对能力无消耗
- 频繁的YoungGC
- 频繁的FullGC
- 高磁盘IO
- 高网络IO
当束手无策时,jmap打印堆栈文件多分析分析吧,或许能灵光一现能找到错误原因。
发现YongGC块,FullGC也快,注定有问题
jstat gcutil pid 100
image
可以看出行O也一直在增加,几乎99,速度很快,老年代一下就满了,立马执行了YongGC,然后进入FGC的速度也快,2天就525了。
进一步排查获取dump文件
通过命令抓取dump文件,进行分析。
jmap -dump:format=b,file=1.hprof pid
分析dump文件
image通过JProfiler分析1.hprof文件
image
image
上述分析结果可以直观的看出,创建的对象线程非常多,并且一直在加,释放很慢。
代码分析
发现程序确实有类似代码
/**
* Provide a new ScheduledExecutorService instance.
*
* <p>A shutdown hook is created to terminate the thread pool on application termination.
*
* @return new ScheduledExecutorService
*/
public static ScheduledExecutorService defaultExecutorService() {
ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(getCpuCount());
Runtime.getRuntime().addShutdownHook(new Thread(() -> shutdown(scheduledExecutorService)));
return scheduledExecutorService;
}
因为此方法是通过一个业务定时器在轮序,2秒一次,每次都去执行了一次,所以造成了内存不足,load值增加,系统负载增加。
解决方法
代码解决
程序改用单例模式,静态方法,执行一次就行。
jvm调优优化
- -XX:MaxTenuringThreshold
- -XX:+ UseConcMarkSweepGC
- -XX:CMSFullGCsBeforeCompaction
具体参数详情请参考[性能调优参数]
调优案例
-XX:MaxTenuringThreshold=0 -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=0
网友评论