当前位置: 首页 > news >正文

实战案例:排查 Java 应用 CPU 飙高问题

实战案例:排查 Java 应用 CPU 飙高问题

一、问题背景

某公司的线上业务系统基于 Java 开发,采用 Spring Boot 框架搭建,部署在 Linux 服务器上。近期,运维人员发现该系统所在服务器的 CPU 使用率持续维持在 90% 以上,导致系统响应缓慢,部分业务请求出现超时现象,严重影响了业务的正常运行。

二、排查过程

(一)初步定位高 CPU 进程

运维人员首先使用 top 命令查看系统中各个进程的资源占用情况:

top

top 输出结果中,按 P 键按照 CPU 使用率进行排序,发现一个名为 java -jar myapp.jar 的进程 CPU 使用率高达 95%,确定该 Java 应用程序是导致 CPU 飙高的罪魁祸首。记录下该进程的 PID(假设为 1234)。

(二)获取该进程内占用 CPU 高的线程

为了进一步定位 Java 应用内部哪个线程占用 CPU 过高,使用 top -Hp <PID> 命令查看该 Java 进程内各个线程的 CPU 占用情况:

top -Hp 1234

在输出结果中,同样按 P 键排序,找到 CPU 使用率最高的线程 ID(假设为 1235)。

(三)将线程 ID 转换为 16 进制

由于 Java 线程栈信息中线程 ID 是 16 进制表示的,所以需要将十进制的线程 ID 转换为 16 进制。可以使用 printf 命令进行转换:

printf "%x\n" 1235

输出结果为 4d3,这就是该线程在 Java 线程栈信息中的表示。

(四)获取 Java 进程的线程栈信息

使用 jstack 命令获取 Java 进程的线程栈信息,并将其保存到文件中:

jstack 1234 > thread_dump.txt

(五)定位问题代码

thread_dump.txt 文件中,使用 grep 命令查找之前转换得到的 16 进制线程 ID:

grep '0x4d3' thread_dump.txt -A 30

在输出结果中,可以看到该线程正在执行的代码栈信息,如下所示:

"Thread-1" #12 prio=5 os_prio=0 tid=0x00007f8c840a3000 nid=0x4d3 runnable [0x00007f8c7b6fa000]
   java.lang.Thread.State: RUNNABLE
        at com.example.myapp.service.MyService.doSomething(MyService.java:56)
        at com.example.myapp.controller.MyController.handleRequest(MyController.java:32)
        at sun.reflect.GeneratedMethodAccessor12.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        ...

从上述信息可以看出,问题出在 com.example.myapp.service.MyService 类的 doSomething 方法的第 56 行。

(六)代码审查与问题分析

开发人员对 MyService.java 文件的第 56 行代码进行审查,发现代码中存在一个死循环:

public class MyService {
    public void doSomething() {
        while (true) {
            // 一些无意义的计算
            int result = 1 + 1;
        }
    }
}

这个死循环导致线程一直在执行计算操作,从而使 CPU 使用率持续居高不下。

三、解决方案

开发人员对代码进行修改,添加了正确的终止条件:

public class MyService {
    private boolean shouldContinue = true;

    public void doSomething() {
        while (shouldContinue) {
            // 一些有意义的业务逻辑
            int result = 1 + 1;
            if (/* 满足某个条件 */) {
                shouldContinue = false;
            }
        }
    }
}

修改完成后,将新的代码部署到生产环境,服务器的 CPU 使用率恢复到正常水平,系统响应也恢复正常。

四、总结与反思

通过本次排查,我们深刻认识到代码逻辑错误对系统性能的严重影响。在开发过程中,应该加强代码审查和测试,避免出现死循环、递归调用过深等问题。同时,运维人员要熟练掌握系统监控和排查工具,以便在出现问题时能够快速定位和解决问题。

http://www.dtcms.com/a/45467.html

相关文章:

  • 自由学习记录(40)
  • HFSS 仿真学习1 K波段定向耦合器
  • JAVA面试_进阶部分_netty面试题
  • 【Java】多线程篇 —— 多线程的基本使用
  • 58、深度学习-自学之路-自己搭建深度学习框架-19、RNN神经网络梯度消失和爆炸的原因(从公式推导方向来说明),通过RNN的前向传播和反向传播公式来理解。
  • 商城源码的框架
  • JAVA学习笔记038——bean的概念和常见注解标注
  • 计算机毕业设计SpringBoot+Vue.js体育馆使用预约平台(源码+文档+PPT+讲解)
  • Pytest之fixture的常见用法
  • AI人工智能机器学习之监督线性模型
  • 【广度优先搜索】图像渲染 岛屿数量
  • 7-1JVMCG垃圾回收
  • 【文献阅读】A Survey Of Resource-Efficient LLM And Multimodal Foundation Models
  • 如何保证 Redis 缓存和数据库的一致性?
  • 在编译Linux的内核镜像和模块时,必须先编译内核镜像,再编译模块,顺序不可随意调整的原因
  • 备战蓝桥杯Day11 DFS
  • React 常见面试题及答案
  • Mysql系统表
  • 【考试大纲】中级信息安全工程师考试大纲
  • HTMLS基本结构及标签
  • 神经网络之CNN图像识别(torch api 调用)
  • 建易WordPress
  • 算法-二叉树篇23-二叉搜索树中的插入操作
  • 夜天之书 #106 Apache 软件基金会如何投票选举?
  • Java 大视界 -- Java 大数据在智能安防入侵检测与行为分析中的应用(108)
  • AF3 DataPipeline类process_core 方法解读
  • sql server 版本更新日期
  • 经典算法 金币阵列问题
  • 【SpringCloud】黑马微服务学习笔记
  • 考虑复杂遭遇场景下的COLREG,基于模型预测人工势场的船舶运动规划方法附Matlab代码