实现一个自动保存高CPU占用现场的简易工具
CPU 使用率在系统监控中是一个非常重要的指标。对于大多数 Web 应用来说,它们往往是 IO 密集型的,因此只会在某些时刻可能会出现 CPU 突然飙升的情况,随后很快就恢复正常。然而,当收到报警并想要排查问题时,CPU 飙升的情况可能已经过去,无法直接查看当时 Java 进程内的线程堆栈信息。
为了解决这个问题,本文实现了一个小工具,它在 CPU 飙升时自动保存堆栈信息,方便后续问题的追踪。
该工具实现了两个主要功能:
- 当 CPU 使用率达到预设的阈值时,自动保存当前 Java 进程的线程堆栈信息;
- 输出占用 CPU 使用率最高的线程 ID。
本文选择在 Linux 系统上实现这个工具,因为大多数应用都是部署在 Linux 环境中(本来想实现一个 MacOS 版本的脚本,但捣鼓了半天,由于格式以及函数存在差异,所以就没继续纠结了)
脚本如下:
#!/bin/bash
if [ $# -ne 1 ]; thenecho "Usage: $0 <j_pid>"exit 1
fij_pid=$1
threshold=90while true; docpu_info=$(ps -p "$j_pid" -o %cpu=)cpu_usage=$(sed 's/%//g' <<< "$cpu_info")current_time=$(date +'%Y-%m-%d %H:%M:%S')echo "[-----$current_time] Current CPU Usage: $cpu_usage%"if [ $(echo "$cpu_usage > $threshold" | bc -q) -eq 1 ]; thenthread_id=$(top -b -n 1 -H -p $j_pid | grep -E "^\s*[0-9]+" | sort -k9 -r | head -n 1 | awk '{print $1}')echo "[-----$current_time] Detected! PID: $j_pid ; Thread ID: $thread_id"jstack_output=$(jstack -l $j_pid)jstack_filename="jstack_$(date +'%Y%m%d%H%M%S').txt"echo "$jstack_output" > "$jstack_filename"echo "[$current_time] jstack_filename: $jstack_filename"fisleep 10
done
可以看看效果,这是模拟的消耗 CPU 的 Java 代码:
/*** @author dongguabai* @date 2023-07-21 13:11*/
public class Test {public static void doSth() {while (true) {double x = Math.random() * Math.random();}}public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {doSth();}}, "highcpu_thread").start();}
}
执行 Java 代码:
[root@MiWiFi-R4CM-srv javaTest]# javac Test.java
[root@MiWiFi-R4CM-srv javaTest]# java Test
执行脚本:
[root@MiWiFi-R4CM-srv javaTest]# sh monitor.sh 9581
[-----2023-07-21 01:37:12] Current CPU Usage: 99.3%
[-----2023-07-21 01:37:12] Detected! PID: 9581 ; Thread ID: 9590
[2023-07-21 01:37:12] jstack_filename: jstack_20230721013713.txt
查看线程 ID:
查看线程堆栈:
"Attach Listener" #9 daemon prio=9 os_prio=0 tid=0xb768fc00 nid=0x25a0 waiting on condition [0x00000000]java.lang.Thread.State: RUNNABLE"DestroyJavaVM" #8 prio=5 os_prio=0 tid=0xb7607400 nid=0x256e waiting on condition [0x00000000]java.lang.Thread.State: RUNNABLE"highcpu_thread" #7 prio=5 os_prio=0 tid=0xb768ec00 nid=0x2576 runnable [0xa4bb8000]java.lang.Thread.State: RUNNABLEat Test.doSth(Test.java:13)at Test$1.run(Test.java:20)at java.lang.Thread.run(Thread.java:748)
可以看到,效果还是可以的。
注意事项
在生产环境中使用此工具时,需要注意以下几点:
jstack
命令可能对系统性能产生一定影响,需要谨慎使用并避免频繁执行- 如果 Java 进程非常大,有很多线程,那么收集线程堆栈信息的操作可能会耗费较多的系统资源
- 触发脚本时 Java 进程本身已经处于高负载状态,运行
jstack
命令可能会导致 Java 进程的响应时间增加 - 最好设置一个触发阈值,频繁地运行
jstack
命令收集线程堆栈信息,可能会在一定程度上增加系统负担
- 脚本最好保存在一个不容易被意外杀掉的地方,以确保在 CPU 飙升时能正常执行。
- 在应用刚启动的时候,可能由于初始化等操作导致短暂的 CPU 飙升,因此脚本可设置延迟执行,避免误报。
相关文章:

实现一个自动保存高CPU占用现场的简易工具
CPU 使用率在系统监控中是一个非常重要的指标。对于大多数 Web 应用来说,它们往往是 IO 密集型的,因此只会在某些时刻可能会出现 CPU 突然飙升的情况,随后很快就恢复正常。然而,当收到报警并想要排查问题时,CPU 飙升的…...

易服客工作室:如何在WordPress网站中举办虚拟活动
您是否正在寻找举办和管理虚拟活动的最佳方式? 也许您想在线举行下一次会议或举办有关您的产品和服务的网络研讨会。您可能担心它太贵,或者您没有技术知识来实现它。 在本文中,我们将列出您所需的在线服务的所有设备,并教您…...

Java IO流(一)IO基础
概述 IO流本质 I/O表示Input/Output,即数据传输过程中的输入/输出,并且输入和输出都是相对于内存来讲Java IO(输入/输出)流是Java用于处理数据读取和写入的关键组件常见的I|O介质包括 文件(输入|输出)网络(输入|输出)键盘(输出)显示器(输出)使用场景 文件拷贝(File&…...
区间覆盖 线段覆盖 二分
4195. 线段覆盖 - AcWing题库 P2082 区间覆盖(加强版) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 做法: void solve() {int n; cin>>n;vector<array<LL,2>> seg(n);for(auto &t: seg) cin>>t[0]>>…...
F#奇妙游(20):主动模式
F#中主动模式的三种形式 F#中有一种特殊的模式匹配,叫做主动模式(Active Pattern)。主动模式可以让我们自定义模式匹配的方式,这样可以让我们的代码更加简洁,更加清晰。主动模式有三种形式,分别是…...

OLED透明屏与传统显示屏的区别:探索未来视觉体验的新里程碑
OLED透明屏作为一种新兴的显示技术,与传统显示屏相比,具有许多独特的特点和优势。 那么,在这篇文章中,尼伽便通过比较OLED透明屏和传统显示屏的区别,包括透明性、对比度、色彩表现力、节能环保等方面,为读…...

打开软件提示mfc100u.dll缺失是什么意思?要怎么处理?
当你打开某个软件或者运行游戏,系统提示mfc100u.dll丢失,此时这个软件或者游戏根本无法运行。其实,mfc100u.dll是动态库文件,它是VS2010编译的软件所产生的,如果电脑运行程序时提示缺少mfc100u.dll文件,程序…...
Python 基础 -- Tutorial(二)
5、数据结构 本章更详细地描述了一些你已经学过的东西,并添加了一些新的东西。 5.1. 更多关于Lists 列表(list)数据类型有更多的方法。下面是列表对象的所有方法: list.append(x) 在列表末尾添加一项。相当于a[len(a):] [x]。 list.extend(iterable) 通过添加可…...
11 迭代器|生成器|协程
文章目录 迭代器可迭代对象可迭代对象的本质iter()函数与 next()函数迭代器 Iterator样例 for...in...循环的本质使用的场景--斐波那契数列list和tuple也可以接收可迭代对象 生成器简介创建生成器方法一方法二总结 使用 send 唤醒 协程协程和线程差异简单实现协程greenletgeven…...

“第三方支付”详解!
第三方支付是什么?第三方支付的解释 中央银行官方解释:是与产品所在国和主要外资银行签订合同、具有一定实力和信誉保障的第三方独立机构提供的交易支持平台。在通过第三方支付平台进行的交易中,买方购买货物后,买方使用第三方平台…...
Rust之泛型、trait与生命周期
泛型是具体类型或其他属性的抽象替代。在编写代码时,可以直接描述泛型的行为,或者它与其他泛型产生的联系,而无须知晓它在编译和运行代码时采用的具体类型。 1、泛型数据类型: 们可以在声明函数签名或结构体等元素时使用泛型&am…...

GPU Microarch 学习笔记 [1]
WARP GPU的线程从thread grid 到thread block,一个thread block在CUDA Core上执行时,会分成warp执行,warp的颗粒度是32个线程。比如一个thread block可能有1024个线程,分成32个warp执行。 上图的CTA(cooperative thre…...

Transformer(一)简述(注意力机制,NLP,CV通用模型)
目录 1.Encoder 1.1简单理解Attention 1.2.什么是self-attention 1.3.怎么计算self-attention 1.4.multi-headed(q,k,v不区分大小写) 1.5.位置信息表达 2.Decoder(待补充) 3.BERT 参考文献 1.Encode…...

回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测
回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测 目录 回归预测 | MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 MATLAB实现BiLSTM双向长短期记忆神经网络多输入多输出预测&#x…...

使用Dockker创建vwas容器时报错的解决方法
执行命令 docker run -it -d -p 13443:3443 --cap-add LINUX_IMMUTABLE secfa/docker-awvs没有详细看报错之前找了各种各样的解决办法,都无法解决。因此以后在看报错提示的时候耐心一点看关键词Error 后来才发现启动vwas时docker报了这个错: OSError: …...

【数据结构OJ题】链表分割
原题链接:https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId8&&tqId11004&rp2&ru/activity/oj&qru/ta/cracking-the-coding-interview/question-ranking 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2…...
无感知发布
什么是无感知发布 "无感知发布"是指在软件系统或应用程序进行更新或升级时,尽可能地避免对用户或系统的正常运行产生影响或中断。这种发布方式通常采用一系列技术和策略,以确保新版本的软件可以平滑地替代旧版本,而不会造成用户的…...

C++ 虚继承
C棱形继承 在 C 中,在使用 多继承 时,如果发生了如果类 A 派生出类 B 和类 C,类 D 继承自类 B 和类 C,这时候就发生了菱形继承。 如果发生了菱形继承,这个时候类 A 中的 成员变量 和 成员函数 继承到类 D 中变成了两…...
git commit用法
git commit 是 Git 版本控制系统中的一个命令,用于将更改提交到本地存储库。以下是 git commit 的一些常见用法和选项: 基本用法: git commit -m "提交信息"使用 -m 选项可以直接在命令行中添加提交信息。 提交所有更改: git commit -a -m &q…...

【LeetCode】543.二叉树的直径
题目 给你一棵二叉树的根节点,返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 示例 1: 输入:root [1,2,3,4,5]…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...

【Linux手册】探秘系统世界:从用户交互到硬件底层的全链路工作之旅
目录 前言 操作系统与驱动程序 是什么,为什么 怎么做 system call 用户操作接口 总结 前言 日常生活中,我们在使用电子设备时,我们所输入执行的每一条指令最终大多都会作用到硬件上,比如下载一款软件最终会下载到硬盘上&am…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...