「性能指标」CPU飙高排查实战

上篇提到了什么是 CPU 以及如何计算的。接下来主要说说实际工作中遇到 CPU 飙高如何去排查呢?

往期回顾:

聊聊性能指标 CPU 利用率如何计算的?

问题发现

前段时间我们新上线了一个应用,由于流量一直不大,集群的每秒查询率(QPS)大约只有 5。接口的响应时间大约在 30 毫秒左右。

最近我们接入了新的业务,业务方提供的数据显示,日常的 QPS 预计可以达到 2000,而在大促期间峰值 QPS 可能会达到 1 万。

为了评估系统的性能水平,我们进行了一次压力测试。测试在预发布环境进行。在压力测试过程中,我们观察到当单台服务器的 QPS 达到约 200 时,接口的响应时间没有明显变化,但是 CPU 利用率迅速上升,直到达到极限。

image.png

压力测试结束后,CPU 利用率立即下降。

随后我们开始排查是什么原因导致了 CPU 的突然飙升。

排查与解决

在压力测试期间,登录到机器后,我们开始排查问题。

本案例的排查过程使用了阿里开源的 Arthas 工具。如果没有 Arthas,也可以使用 JDK 自带的命令进行排查。

在开始具体排查之前,可以先查看 CPU 的使用情况。最简单的方法是使用top命令直接查看:

top - 10:32:38 up 11 days, 17:56,  0 users,  load average: 0.84, 0.33, 0.18
Tasks:  23 total,   1 running,  21 sleeping,   0 stopped,   1 zombie
%Cpu(s): 95.5 us,  2.2 sy,  0.0 ni, 76.3 id,  0.0 wa,  0.0 hi,  0.0 si,  6.1 st
KiB Mem :  8388608 total,  4378768 free,  3605932 used,   403908 buff/cache
KiB Swap:        0 total,        0 free,        0 used.  4378768 avail MemPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND3480 admin     20   0 7565624   2.9g   8976 S  241.2 35.8 649:07.23 java1502 root      20   0  401768  40228   9084 S   1.0  0.5  39:21.65 ilogtail181964 root      20   0 3756408 104392   8464 S   0.7  1.2   0:39.38 java496 root      20   0 2344224  14108   4396 S   0.3  0.2  52:22.25 staragentd1400 admin     20   0 2176952 229156   5940 S   0.3  2.7  31:13.13 java235514 root      39  19 2204632  15704   6844 S   0.3  0.2  55:34.43 argusagent236226 root      20   0   55836   9304   6888 S   0.3  0.1  12:01.91 systemd-journ

可以清楚的看到,进程 ID 为 3480 的 Java 进程占用了较高的 CPU,可以初步推断是应用代码执行过程中消耗了大量的 CPU 资源。接下来,我们需要进一步排查是哪个线程、哪段代码导致了这种情况。

首先,我们需要下载 Arthas 工具:

curl -L https://arthas.aliyun.com/install.sh | sh

启动:

./as.sh

使用 Arthas 命令 "thread -n 3 -i 1000"查看当前"最忙"(耗 CPU)的三个线程:

image.png

通过上述堆栈信息可以看出,占用 CPU 资源的线程主要是在 JDBC 底层的 TCP 套接字读取上阻塞。经过连续执行多次分析,发现很多线程都在这个地方卡住。

进一步分析调用链后发现,这个问题源自于我代码中的数据库 insert 操作,其中使用了 TDDL 来创建 sequence。在 sequence 的创建过程中,需要与数据库进行交互。

根据对 TDDL 的了解,它每次从数据库查询 sequence 序列时,默认会获取 1000 条,并在本地进行缓存,直到使用完这 1000 条序列之后才会再次从数据库获取下一个 1000 条序列。

考虑到我们的压测 QPS 仅约为 300 左右,不应该导致如此频繁的数据库交互。然而,通过多次使用 Arthas 进行查看,发现大部分的 CPU 资源都耗费在这里。

因此,我们开始排查代码问题。最终,发现了一个非常简单的问题,即我们的 sequence 创建和使用存在着明显的缺陷:

public Long insert(T dataObject) {if (dataObject.getId() == null) {Long id = next();dataObject.setId(id);}if (sqlSession.insert(getNamespace() + ".insert", dataObject) > 0) {return dataObject.getId();} else {return null;}
}public Sequence sequence() {return SequenceBuilder.create().name(getTableName()).sequenceDao(sequenceDao).build();
}/*** 获取下一个主键ID** @return*/
protected Long next() {try {return sequence().nextValue();} catch (SequenceException e) {throw new RuntimeException(e);}
}

因此,我们每次执行 insert 语句时都重新构建了一个新的 sequence 对象,这导致本地缓存被清空。因此,每次都需要从数据库重新获取 1000 条 sequence,但实际上只使用了一条,下次又会重复这个过程。

为了解决这个问题,我们调整了代码,在应用启动时初始化了一个 Sequence 实例。这样,在后续获取 sequence 时,不会每次都与数据库交互。而是首先检查本地缓存,只有在本地缓存用尽时才会再次与数据库交互,获取新的 sequence。

public abstract class BaseMybatisDAO implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {sequence = SequenceBuilder.create().name(getTableName()).sequenceDao(sequenceDao).build();}}

通过实现 InitializingBean 接口,并重写其中的 afterPropertiesSet()方法,在该方法中进行 Sequence 的初始化。

完成以上代码修改后,提交并进行验证。根据监控数据显示,优化后数据库的读取响应时间(RT)明显下降。

image.png
sequence 的写操作 QPS 也有明显下降:

image.png

于是我们开始了新的一轮压测,但是发现 CPU 的使用率仍然很高,压测的 QPS 还是无法达到预期。因此,我们决定重新使用 Arthas 工具查看线程的情况。

image.png

发现了一个 CPU 消耗较高的线程堆栈,主要是因为我们在使用一个联调工具时,该工具预发布状态下默认开启了 TDDL 的日志采集(尽管官方文档中描述预发布状态下默认不会开启 TDDL 采集,但实际上确实会进行采集)。

在该工具打印日志时,会进行数据脱敏操作,脱敏框架使用了 Google 的 re2j 进行正则表达式匹配。

由于我的操作涉及到大量的 TDDL 操作,而默认情况下会采集大量 TDDL 日志并进行脱敏处理,这导致了较高的 CPU 消耗。

因此,通过在预发布环境中关闭对 TDDL 的日志采集,可以有效解决这个问题。

总结

这篇总结回顾了一次线上 CPU 飙高问题的排查过程,虽然问题最终解决起来并不复杂,但排查过程中却有其独特的教育意义。

之前经验丰富的我按照惯例进行了排查,初始阶段并未发现明显问题,错误地将数据库操作增加归因于流量上升所致的正常情况。

通过多方查证(例如使用 arthas 查看序列获取情况,以及通过数据库查询最新插入数据的主键 ID 等方法),最终确认问题出在 TDDL 的序列初始化机制上。

解决了这个问题后,本以为问题彻底解决,却又遭遇到 DP 采集 TDDL 日志导致 CPU 飙高的情况,最终再次解决问题后系统性能有了显著提升。

因此,这个经历再次验证了“事出反常必有妖”,排查问题确实需要有耐心和系统性。

如有问题,欢迎微信搜索【码上遇见你】。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/36787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣 单链表元素删除解析及高频面试题

目录 删除元素的万能方法 构造虚拟头结点来应对删除链表头结点的情况 一、203.移除链表元素 题目 题解 二、19.删除链表中倒数第K个节点 题目 题解 三、 83.删除某个升序链表中的重复元素,使重复的元素都只出现一次 题目 题解 82.删除某个升序链表中的…

2023年第十四届蓝桥杯JavaB组省赛真题及全部解析(下)

承接上文:2023年第十四届蓝桥杯JavaB组省赛真题及全部解析(下)。 目录 七、试题 G:买二赠一 八、试题 H:合并石子 九、试题 I:最大开支 十、试题 J:魔法阵 题目来自:蓝桥杯官网…

【星海随笔】vue+vite

开头问一个问题&#xff0c;我发现有的人粉丝是点赞数的好几倍&#xff0c;可能和必须关注他才能阅读他的文章有关。 所以问一下怎么设置为关注才能查看该文章。 screen -ls #查看 id 列表 screen -S <session_name> # 创建一个会话 screen -R <session_id> # 根据…

iconfont-阿里巴巴矢量图标库 在vue项目使用记录

官网地址&#xff1a;https://www.iconfont.cn/manage/index?manage_typemyprojects&projectId4539761 第一步&#xff1a; 下载资源 ->解压到项目文件夹 第二步 在项目中main.ts 或者main.js 引入资源 import //assets/iconfont/font/iconfont.js; import //assets…

IBM Spectrum LSF RTM,针对 IBM Spectrum LSF 环境的高级报告、跟踪和监控工具

亮点 为 IBM Spectrum LSF 环境提供性能监控和报告 监控 FlexNet Publisher 和 Reprisebased 许可证的使用&#xff0c;提供详细和总结性报告 通过多个级别&#xff08;包括应用程序和组织&#xff09;的报告来监控共享存储的利用率 提供强大的生产力工具&#xff0c;包括操…

JVM专题五:类加载器与双亲委派机制

通过上一篇Java的类加载机制相信大家已经搞明白了整个类加载从触发时机&#xff0c;接着我们就来看下类加载器&#xff0c;因为类加载机制是有加载器实现的。 类加载器的分类 启动类加载器 Bootstrap ClassLoader 是 Java 虚拟机&#xff08;JVM&#xff09;的一部分&#x…

斜光测距的原理及python实现

1.前言 最近做了一个基于opencv的斜光测距的小项目&#xff0c;东西不多&#xff0c;但是很有意思&#xff0c;值得拿出来学一学。项目里面需要比较精确的定位功能&#xff0c;将前人matlab代码移植到python上&#xff0c;并且做了一些优化&#xff0c;简化逻辑(毕竟我是专业的…

我教会了我妈搭建自己的 AI 聊天机器人...

在这个人工智能爆发的年代,ChatGPT、Claude、Kimi、文心一言等 AI 大模型产品火遍全网,仿佛一夜之间,人人都在谈论 AI。 作为普通人的我们,难道就只能看着程序员们尽情玩耍,自己却无法参与其中吗?NO! 鉴于最近自己社群学员和粉丝的要求&#xff0c;一进来大家无论是不是小白…

Linux防火墙【SNAT,DNAT】

NAT: 支持PREROUTING&#xff0c;INPUT&#xff0c;OUTPUT&#xff0c;POSTROUTING四个链 请求报文&#xff1a;修改源/目标IP&#xff0c; 响应报文&#xff1a;修改源/目标IP&#xff0c;根据跟踪机制自动实现 NAT的实现分为下面类型&#xff1a; SNAT&#xff1a;source…

如何实现数字人系统私有化部署?数字人源码部署教程简易版来了!

当前&#xff0c;数字人行业的市场前景和应用潜力不断显现&#xff0c;不少创业者都想要通过学习数字人源码部署教程来搭建属于自己的数字人系统&#xff0c;以此获得进军数字人行业的入场券。而事实上&#xff0c;该想法本身当然是固然值得鼓励的&#xff0c;但就目前的实践情…

基于改进天鹰优化算法(IAO)优化RBF神经网络数据回归预测 (IAO-RBF)的数据回归预测(多输入多输出)

改进天鹰优化算法(IAO)见&#xff1a;【智能优化算法】改进的AO算法(IAO)-CSDN博客 代码原理 基于改进天鹰优化算法&#xff08;IAO&#xff09;优化RBF神经网络数据回归预测&#xff08;IAO-RBF&#xff09;的多输入多输出&#xff08;MIMO&#xff09;数据回归预测&#xf…

视频去水印软件?在线去除视频水印工具网站?

视频去水印软件哪个好&#xff1f;在数字时代&#xff0c;视频内容的传播变得日益普遍&#xff0c;然而&#xff0c;许多视频带有水印&#xff0c;影响了观看体验&#xff0c;如果有这些图案我们需要找方法把这些图案从视频上去掉。今天我们就来看一下视频去水印的超级简单的方…

添加阈值滞后以实现平滑的欠压/过压锁定

电阻分压器将高压衰减到低压电路可以承受的水平&#xff0c;而不会过驱动或损坏。在电源路径控制电路中&#xff0c;电阻分压器有助于设置电源欠压和过压锁定阈值。这种电源电压鉴定电路存在于汽车系统、电池供电的便携式仪器以及数据处理和通信板中。 欠压锁定 (UVLO) 可防止…

goLang小案例-打印99乘法表

goLang小案例-打印99乘法表 1. 打印99乘法表 func Print99multiplication1() {//横向9排for i : 1; i < 9; i {//竖向9列//第一批第一个 和第一列比较 如果大于排就结束//假设第三排i3 最走有三列 1*3 2*3 3*3//j3打印完 j 当j4就要结束 以此类推for j : 1; j < i; j …

蓝牙耳机推荐学生党怎么选?300左右蓝牙耳机分享

在选择蓝牙耳机时&#xff0c;学生党需要考虑的因素包括音质、续航力、舒适度以及连接稳定性等&#xff0c;而在300元左右的价位&#xff0c;虽然不能期待与高端产品相媲美的性能&#xff0c;但依然有一些性价比较高的选择能够满足大部分的日常需求&#xff0c;下面给大家推荐几…

使用python基于经纬度获取高德地图定位地址【逆地址解析】

一、高德地图api申请 1. 高德开放平台注册&#xff0c;登录 进入网址&#xff1a;高德开放平台 | 高德地图API 注册 -- 支付宝扫码认证 -- 完善个人信息 -- 登录 2. 申请API &#xff08;1&#xff09;点击头像 -- 应用管理 -- 我的应用 -- 创建新应用 &#xff08;2&…

【papaparse插件】前端预览csv文件

需求&#xff1a;就是可以在前端直接预览csv文件的内容 1.了解csv文件 1.1 csv文件和xlsx、xls文件的异同 首先了解一下csv文件和excel文件&#xff08;xlsx&#xff0c;xls&#xff09;有什么异同&#xff0c;简单来说他们都是存储表格数据的文件&#xff0c;csv只能显示较…

一站式AI服务平台:MaynorAI助您轻松驾驭人工智能

一站式AI服务平台&#xff1a;MaynorAI助您轻松驾驭人工智能 在当前的数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;技术已经成为推动各行各业创新发展的核心动力。为了更好地满足企业和个人用户对AI服务的需求&#xff0c;MaynorAI 作为一个领先的一站式调用国内…

【oracle】oracle索引分裂

本文为云贝教育 刘峰 原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 一、索引分裂概述 Oracle数据库中的索引分裂是数据库维护和性能管理中的一个重要概念&#xff0c;特别是在处理大量数据插入、更新和…

CVPR 2024最佳论文分享:生成图像动力学

CVPR 2024最佳论文分享&#xff1a;生成图像动力学 CVPR&#xff08;Conference on Computer Vision and Pattern Recognition&#xff09;是计算机视觉领域最有影响力的会议之一&#xff0c;主要方向包括图像和视频处理、目标检测与识别、三维视觉等。近期&#xff0c;CVPR 2…