再一次生产 CPU 高负载排查实践

前言
前几日早上打开邮箱收到一封监控报警邮件:某某 ip 服务器 CPU 负载较高,请研发尽快排查解决,发送时间正好是凌晨。
其实早在去年我也处理过类似的问题,并记录下来:《一次生产 CPU 100% 排查优化实践》
不过本次问题产生的原因却和上次不太一样,大家可以接着往下看。
问题分析
收到邮件后我马上登陆那台服务器,看了下案发现场还在(负载依然很高)。
于是我便利用这类问题的排查套路定位一遍。
首先利用 top -c 将系统资源使用情况实时显示出来 (-c 参数可以完整显示命令)。
接着输入大写 P 将应用按照 CPU 使用率排序,第一个就是使用率最高的程序。
果不其然就是我们的一个 Java 应用。
这个应用简单来说就是定时跑一些报表使的,每天凌晨会触发任务调度,正常情况下几个小时就会运行完毕。
常规操作第二步自然是得知道这个应用中最耗 CPU 的线程到底再干嘛。
利用 top -Hp pid 然后输入 P 依然可以按照 CPU 使用率将线程排序。
这时我们只需要记住线程的 ID 将其转换为 16 进制存储起来,通过 jstack pid >pid.log 生成日志文件,利用刚才保存的 16 进制进程 ID 去这个线程快照中搜索即可知道消耗 CPU 的线程在干啥了。
如果你嫌麻烦,我也强烈推荐阿里开源的问题定位神器 arthas 来定位问题。
比如上述操作便可精简为一个命令 thread -n 3 即可将最忙碌的三个线程快照打印出来,非常高效。
更多关于 arthas 使用教程请参考官方文档。
由于之前忘记截图了,这里我直接得出结论吧:
最忙绿的线程是一个 GC 线程,也就意味着它在忙着做垃圾回收。
GC 查看
排查到这里,有经验的老司机一定会想到:多半是应用内存使用有问题导致的。
于是我通过 jstat -gcutil pid 200 50 将内存使用、gc 回收状况打印出来(每隔 200ms 打印 50次)。

从图中可以得到以下几个信息:
Eden区和old区都快占满了,可见内存回收是有问题的。fgc回收频次很高,10s 之内发生了 8 次回收((866493-866485)/ (200 *5))。- 持续的时间较长,fgc 已经发生了 8W 多次。
内存分析
既然是初步定位是内存问题,所以还是得拿一份内存快照分析才能最终定位到问题。
通过命令 jmap -dump:live,format=b,file=dump.hprof pid 可以导出一份快照文件。
这时就得借助 MAT 这类的分析工具出马了。
问题定位

通过这张图其实很明显可以看出,在内存中存在一个非常大的字符串,而这个字符串正好是被这个定时任务的线程引用着。

大概算了一下这个字符串所占的内存为 258m 左右,就一个字符串来说已经是非常大的对象了。
那这个字符串是咋产生的呢?
其实看上图中的引用关系及字符串的内容不难看出这是一个 insert 的 SQL 语句。
这时不得不赞叹 MAT 这个工具,他还能帮你预测出这个内存快照可能出现问题地方同时给出线程快照。


最终通过这个线程快照找到了具体的业务代码:
他调用一个写入数据库的方法,而这个方法会拼接一个 insert 语句,其中的 values 是循环拼接生成,大概如下:
<insert id="insert" parameterType="java.util.List">
insert into xx (files)
values
<foreach collection="list" item="item" separator=",">
xxx
</foreach>
</insert>
所以一旦这个 list 非常大时,这个拼接的 SQL 语句也会很长。

通过刚才的内存分析其实可以看出这个 List 也是非常大的,也就导致了最终的这个 insert 语句占用的内存巨大。
优化策略
既然找到问题原因那就好解决了,有两个方向:
- 控制源头
List的大小,这个List也是从某张表中获取的数据,可以分页获取;这样后续的insert语句就会减小。 - 控制批量写入数据的大小,其实本质还是要把这个拼接的
SQL长度降下来。 - 整个的写入效率需要重新评估。
总结
本次问题从分析到解决花的时间并不长,也还比较典型,其中的过程再总结一下:
- 首先定位消耗
CPU进程。 - 再定位消耗
CPU的具体线程。 - 内存问题
dump出快照进行分析。 - 得出结论,调整代码,测试结果。
最后愿大家都别接到生产告警。
你的点赞与分享是对我最大的支持
再一次生产 CPU 高负载排查实践的更多相关文章
- Mysql 高负载排查思路
Mysql 高负载排查思路 发现问题 top命令 查看服务器负载,发现 mysql竟然百分之两百的cpu,引起Mysql 负载这么高的原因,估计是索引问题和某些变态SQL语句. 排查思路 1. 确定高 ...
- CPU高问题排查
双11大战开始了,这几天公司系统压测,CPU各种报警,于是找了篇关于CPU高问题排查的文章. 一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. (友情提示:本博文章欢迎 ...
- CPU负载过高异常排查实践与总结
昨天下午突然收到运维邮件报警,显示数据平台服务器cpu利用率达到了98.94%,而且最近一段时间一直持续在70%以上,看起来像是硬件资源到瓶颈需要扩容了,但仔细思考就会发现咱们的业务系统并不是一个高并 ...
- 服务器 CPU 100% 异常排查实践与总结
一个执着于技术的公众号 问题背景 昨天下午突然收到运维邮件报警,显示数据平台服务器cpu利用率达到了98.94%,而且最近一段时间一直持续在70%以上,看起来像是硬件资源到瓶颈需要扩容了,但仔细思考就 ...
- Ubuntu1804下k8s-CoreDNS占CPU高问题排查
1.背景: 最近在ubuntu804上适配k8s的时候,部署到业务pod的时候,出现了服务器卡死,top查看发现负载很高,进行CPU排序发现如下信息,可知是CoreDNS服务导致. 2. 分析排查: ...
- 服务器负载过高问题分析-不是cpu高负载也不是IO负载如何处理(阿里 几乎是必考题)
关于top命令 经常问load average 参考:load average 定义(网易面试) jvm dump的使用 参考:Jvm dump jstack jmap jstat 介绍与使用(内存与 ...
- CPU高的排查
之前有朋友反馈说发的内容希望有个梯度,逐步加深,前面发了几篇关于jvm源码分析的文章,可能我觉得我已经把内容写得浅显易懂了,但是对于某些没怎么接触的同学来说还是比较难理解,这个我以后慢慢改进吧,今天发 ...
- 生产环境下JAVA进程高CPU占用故障排查
问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过, ...
- 生产环境下JAVA进程高CPU占用故障排查---temp
问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过, ...
随机推荐
- SERCOS总线程序相关
SERCOS程序就是围绕主机发送MDT电报,伺服在下一个周期发送AT电报作为应答这个原则来实现的,这个过程是由控制字等控制实现的,读程序的时候如果忽略这点,可能在想程序从哪里读数据,在哪里写数据呢.. ...
- 如何在Oracle 12C中Drop/Truncate多个分区 (Doc ID 1482264.1)
How to Drop/Truncate Multiple Partitions in Oracle 12C (Doc ID 1482264.1) APPLIES TO: Oracle Databas ...
- 基于django的个人博客网站建立(七)
基于django的个人博客网站建立(七) 前言 网站效果可点击这里访问 这次在原来的基础上添加或修改一些小功能 具体内容 1.代码高亮 在原来的blog-details.html页面添加下面的代码: ...
- swoole比php好在哪里
直接套用Swoole官网的介绍: PHP的异步.并行.高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接 ...
- Eureka工作原理及它和ZooKeeper的区别
1.Eureka 简介: Eureka 是 Netflix 出品的用于实现服务注册和发现的工具. Spring Cloud 集成了 Eureka,并提供了开箱即用的支持.其中, Eureka 又可细分 ...
- 跨域问题,解决方案-Nginx反向代理
跨域问题,解决之道 跨域问题,在日常开发过程中,是一个非常熟悉的名词.今天的话题,结合我之前的项目场景,讨论下<跨域问题,解决之道>. 跨域是什么 跨域问题,是由于JavaScript出于 ...
- VUE Base64编码图片展示与转换图片
图片的 base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址,使用 base64 传输图片文件可以节省一个 http 请求,图片的 base64 编码可以算是前端优化的一 ...
- netcore3.0配置跨域
netcore3.0框架已集成了Microsoft.AspNetCore.Mvc.Cors包,因此不需要单独引用. 在ConfigureServices中添加Cors策略服务 services.Add ...
- 服务器返回的数据将Unicode码转成汉字
当我们请求接口的时候,服务器会返回一些数据,当我们打印的时候就会发现,打印出来的是unicode码,不是汉字. 这时候需要我们自己手动处理一下,让打印的时候输出汉字的格式. 方法如下: 新增一个分类, ...
- 检测到无法识别的AP,请升级AP数据库
0x00 事件 原因是公司新增了两个 AP 设备 TL-AP1202i ,似乎是新的 AP 硬件版本比较高,导致 AC 无法识别,控制器 Web 页面给出 检测到无法识别的AP,请升级AP数据库! 的 ...