【记录问题排查系列】记录CPU飙高问题排查过程篇(1)

在这里插入图片描述

CPU飙高问题排查

    • ✔️问题排查与解决
    • ✔️总结与思考


🍁前段时间我们新上了一个新的应用,因为流量一直不大,集群OPS大概只有5左右,写接口的t在30ms左右。


因为最近接入了新的业务,业务方给出的数据是日常QPS可以达到2000,大促峰值QPS可能会达到1万。


所以,为了评估水位,我们进行了一次压测。压测在预发布环境执行。压测过程中发现,当单机QPS达到200左右时,接口的rt没有明显变化,但是CPU利用率急剧升高,直到被打满。


在这里插入图片描述

压测停止以后,CPU利用率立刻就降了下来。


于是就开始排查什么导致了CPU的暴增问题。


✔️问题排查与解决


在压测期间,登录到机器,开始排查问题。


这个案例的排查过程使用的阿里开源的Arthas工具进行的,不适用arthas,使用JDK自带的命令也是可以的。


在开始排查之前,可以先看一下CPU的使用情况,最简单的就是使用Top命令直接查看:


在这里插入图片描述

可以看到,进程ID为3480的Java进程占用的CPU比较高,基本可以断定是应用代码执行过程中消耗了大量CPU接下来开始排查具体是哪个线程,哪段代码比较耗CPU。


首先,下载Arthas命令:


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


启动:


./as . sh


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


在这里插入图片描述

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


通讨分析调用链,发现这个地方是我代码中有数据库的insert,并且使用TDDL来创建sequence,在sequence的创建过程中需要和数据库有交互。


但是,基于对TDDL的了解,TDDL每次从数据库中查询sequence序列的时候,默认会取出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(getTablelame()).sequenceDao(sequenceDao).build();
}/**
*    获取下一个主键ID
*
*   @return
*/protected Long next() {try {return sequence().nextValue();} catch (SequenceException e) {throw new RuntimeException(e);}
}

是因为,我们每次insert语句都重新build了一个新的sequence,这就导致本地缓存就被丢掉了,所以每次都会去数据库中重新拉取1000条,但是只是用了一条,下一次就又重新取了1000条,周而复始。


于是,调整了代码,把Sequence实例的生成改为在应用启动时初始化一次。这样后面在获取sequence的时候不会每次都和数据库交互,而是先查本地缓存,本地缓存的耗尽了才会再和数据库交互,获取新的sequence。


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

通过实现nitializingBean,并目重写afterPropertiesSet0万法,在这方法中进行Seguence的初始化。


改完以上代码,提交进行验证。通过监控数据可以看出优化后,数据库的读RT有明显下降:


在这里插入图片描述

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


在这里插入图片描述

于是我们开始了新的一轮压测,但是发现,CPU的使用率还是很高,压测的QPS还是上不去,于是重新使用Arthas查看线程的情况。


在这里插入图片描述

发现了一个新的比较耗费CPU的线程的堆栈,这里面主要是因为我们用到了一个联调工具,该工具预发布默认开启了TDDL的采集(官方文档中描述为预发布默认不开启TDDL采集,但是实际上会采集)。


这个工具在打印日志过程中会进行脱敏,脱敏框架会调用Google的re2i进行正则表达式的匹配。


因为我的操作中TDDL操作比较多,默认采集大量TDDL日志并且进行脱敏外理,确实比较耗费CPU。


所以,通过在预发布中关闭DP对TDDL的采集,即可解决该问题。


✔️总结与思考


本文总结了一次线上CPU飙高的问题排查过程,其实问题都不难,并且还挺傻的,但是这个排查过程是值得大家学习的。


其实在之前自己排查过很多次CPU飙高的问题,这次也是按照老方法进行排查,但是刚开始并没有发现太大的问题,只是以为是流量升高导致数据库操作变多的正常现象。


期间又多方查证(通过arthas查看sequence的获取内容、通过数据库查看最近插入的数据的主键ID等)才发现是TDDL的Sequence的初始化机制有问题。


在解决了这个问题之后,以为彻底解决问题,结果又遇到了DP采集TDDL日志导致CPU飙高,最终再次解决后有
了明显提升。


所以,事出反常必有妖,排查问题就是一个抽丝剥茧的过程。

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

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

相关文章

无人职守自动安装linux操作系统

无人职守自动安装linux操作系统 1. 大规模部署案例2. PXE 技术3. Kickstart 技术4. 配置安装服务器4.1 DHCP服务4.2 TFTP 服务4.3 NFS服务 5. 示例5.1 搭建server1. 启动dhcp并设为开机自启2. 设置并启动tftp3. 将客户端所需启动文件复制到TFTP服务器4. 创建Kickstart自动应答文…

【IO】IO模型与零拷贝

前言: 正在运行的程序其实就是系统中的一个进程,操作系统会为每一个进程分配内存空间,而内存空间分为两部分,一部分是用户空间,这是用户进程访问的内存区域;另一部分是内核空间,是操作系统内核访…

20种常用的软件测试方法,建议先收藏再观看

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

简单的喷淋实验(2):(1)根据土壤湿度自动控制喷淋开关;(2)根据光照强度控制风扇以及灯的开关---嵌入式实训

目录 简单的喷淋实验(2): (1)根据土壤湿度自动控制喷淋开关; (2)根据光照强度控制风扇以及灯的开关---嵌入式实训 任务2: 具体过程: 所用的头文件: data_global.h …

gin框架使用系列之三——获取表单数据

系列目录 《gin框架使用系列之一——快速启动和url分组》《gin框架使用系列之二——uri占位符和占位符变量的获取》 一、获取get参数 get请求的参数是直接加在url后面的,在gin中获取get请求的参数主要用Query()和DefaultQuery()两个方法,示例代码如下…

【Unity地形】使用地形工具创建场景环境-Terrain

如上图Unity的地形工具可以让我们实现创建复杂、丰富的3D室外环境。 我们创建地形很简单,在层级面板中右键-3Dobject-Terrain 就可以创建一个默认的地形模型!这个模型是Unity内置的。 接下来的地形编辑功能全部集中在这个地形的组件上 主要功能如下&…

WPS中如何根据身份证号生成出生日期并排序

1. wps中如何根据身份证号导出出生日期并排序 1.1 wps中建一张表 1.2 使用转日期格式导出出生日期 DATE(VALUE(MID(C2,7,4)),VALUE(MID(C2,11,2)),VALUE(MID(C2,13,2)))MID(C2, 7, 4):这部分从单元格 C2 中提取文本字符串,从第7个字符开始提取长度为4的…

[python]python使用M-LSD直线检测算法onnx部署模型实时检测

介绍 github地址:https://github.com/navervision/mlsd LSD (M-LSD)一种用于资源受限环境的实时轻量线段检测器。它利用了极其高效的 LSD 架构和新颖的训练方案,包括 SoL 增强和几何学习方案。模型可以在GPU、CPU甚至移动设备上实时运行。算法已开源&a…

【elk-day01】es和kibana搭建及验证---Mac-Docker

Mac系统使用Docker下载搭建和验证eskibana Docker下载安装es安装es验证kibana安装kibana验证 Docker下载安装 Docker Desktop官网安装下载地址 说明一下为什么要安装desktop版本的docker,因为docker作为工具使用,我们需要的是开箱即用,没有必…

windows搭建MySQL 8.25主从配置

1.本次搭建的版本 mysql-8.0.25-win-x64 2.在解压完成后的文件内并没有对应的my.ini的配置文件这个my.ini是需要的主配置文件需要自行创建。 注:安装路径及数据存放路径需根据实际安装情况进行修改(其它配置信息可结合实际情况进行修改) 3.在…

vue+element实现动态表格:根据后台返回的属性名和字段动态生成可变表格

现有一个胡萝卜厂生产不同品种的胡萝卜,为了便于客户了解产品,现需在官网展示胡萝卜信息。现有的萝卜信息:编号(id)、名称(name)、保质期(age)、特点(remark&…

深度学习:计算机技术的革命性突破

深度学习:计算机技术的革命性突破 随着科技的飞速发展,深度学习已经成为计算机技术领域的一股强大力量。它改变了我们与机器的交互方式,为人工智能领域带来了革命性的突破。本篇博客将深入探讨深度学习的原理、应用和发展趋势。 一、深度学…

【python】爬取斗鱼直播照片保存到本地目录【附源码+文末免费送书】

一、导入必要的模块: 这篇博客将介绍如何使用Python编写一个爬虫程序,从斗鱼直播网站上获取图片信息并保存到本地。我们将使用requests模块发送HTTP请求和接收响应,以及os模块处理文件和目录操作。 如果出现模块报错 进入控制台输入&#xff…

【基础篇】五、类的双亲委派机制

文章目录 1、双亲委派机制2、Java代码中去主动加载一个类3、“父”加载器4、Q & A5、打破双亲委派机制 1、双亲委派机制 JVM中有多个类加载器,某个类A,到底该由谁去加载 ⇒ 双亲委派机制 该机制的作用: 保证类加载的安全性:避…

Grafana 配置告警

配置告警 配置告警 1. Grafana 配置文件配置 #################################### SMTP / Emailing ########################## [smtp] enabled true host smtp.qq.com:587 user 9**qq.com # If the password contains # or ; you have to wrap it with triple quotes…

智能优化算法应用:基于白鲸算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用:基于白鲸算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于白鲸算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.白鲸算法4.实验参数设定5.算法结果6.参考文献7.MA…

vue3+elementPlus+cascader动态加载封装自定义组件+v-model指令实现父子通信

文章目录 select普通操作 (1)cascader操作(2) select普通操作 (1) 搜索条件需求:接口入参需要houseId,但是要先选择完楼栋,再选择单元,最后选择房屋 如图&a…

【C#】.net core 6.0 依赖注入生命周期

给自己一个目标,然后坚持一段时间,总会有收获和感悟! 对于.net core而言,依赖注入生命周期有三种瞬态(Transient)、作用域(Scoped)和单例(Singleton)&#xf…

数据结构-如何实现一个队列?逐步解析与代码示例(超详细)

文章目录 前言1.队列的基本概念2.链表与数组实现队列的区别2.1数据存储结构2.2性能2.3内存使用 3.为什么选择链表实现队列?4.结构定义函数声明 5.核心操作5.1初始化 (QInit)5.2销毁 (QDestroy)5.3入队 (QPush)5.4出队 (QPop) 6.队列的查询操作6.1队首元素 (QueueFro…

如何将语音版大模型AI接入自己的项目里(语音ChatGPT)

如何将语音版大模型AI接入自己的项目里语音ChatGPT 一、语音版大模型AI二、使用步骤1、接口2、请求参数3、请求参数示例4、接口 返回示例5、智能生成API代码 三、 如何获取appKey和uid1、申请appKey:2、获取appKey和uid 四、重要说明 一、语音版大模型AI 基于阿里通义千问、百…