[Java实战]Spring Boot服务CPU 100%问题排查:从定位到解决

Spring Boot服务CPU 100%问题排查:从定位到解决

1. 引言

当Spring Boot服务出现CPU占用率100%时,系统性能会急剧下降,甚至导致服务不可用。本文将通过真实代码案例,详细讲解如何快速定位问题根源,并提供解决方案。无论是死循环、线程阻塞还是资源泄漏,本文帮你一网打尽!

2. 问题现象

  • 服务器CPU使用率持续100%
  • 接口响应时间变长或超时
  • 通过监控工具(如Grafana、Arthas)发现异常线程

3. 排查步骤

3.1 编写测试代码

在这里插入图片描述

3.2 运行代码效果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3 定位高CPU进程

使用top命令快速找到占用CPU最高的Java进程:

top -c   # 显示完整命令,找到PID

终端输入命令:top -c,找到高cpu进程PID:420364

在这里插入图片描述

3.4 定位高CPU线程

通过top -Hp <PID>查看进程内线程的CPU使用情况,记录线程ID(需转换为十六进制):

#查找进程中的线程
top -Hp <PID>top -Hp 420364# 假设线程ID为433127 → 69be7 输出为16进制printf "%x\n" 433127 [root@localhost java]# printf "%x\n" 433127 
69be7

终端输入命令:top -Hp 420364,定位高cpu线程:433127

线程ID转换为16进制:69be7

生成堆栈信息:jstack 420364 > stack.log 生成时PID:420364

通过堆栈信息分析:grep -A 20 ‘nid=0x69be7’ stack.log nid=0x69be7为线程id

根据信息对比原代码可找到问题

在这里插入图片描述

3.5分析线程堆栈

使用jstack捕获线程堆栈并分析:

#生成线程堆栈
jstack <PID> > stack.logjstack 420364 > stack.log# 搜索特定线程
grep -A 20 'nid=0x69be7' stack.log 

在这里插入图片描述

在这里插入图片描述

排查结果及源代码问题对比:类32行运行结果导致cpu 100%

在这里插入图片描述

3.5 Arthas 工具定位

以上是根据Java自带的jstack 工具定位, Arthas 工具也能定位排查。定位思路和上面步骤一致

#安装下载启动
curl -O https://arthas.aliyun.com/arthas-boot.jarjava -jar arthas-boot.jar

启动选择需要定位项目:2

在这里插入图片描述

直接输入查看高cpu线程: thread

在这里插入图片描述

查看堆栈信息找到代码问题: thread 29 (线程ID)

在这里插入图片描述

如果想看实时面板信息: dashboard

在这里插入图片描述

4. 常见原因与代码示例

4.1 死循环(While循环未正确退出)

问题代码

@Service
public class CpuProblemController {public void deadLoop() {while (true) {  // 无条件退出,导致死循环// 业务逻辑(如未正确更新循环条件)}}
}

解决方案

@Service
public class CpuProblemController {private volatile boolean running = true;  // 添加退出标志public void deadLoop() {while (running) {  // 通过控制running变量退出循环// 业务逻辑}}@PreDestroypublic void stop() {running = false;  // 服务关闭时触发退出}
}

测试完整类:

package com.example.controller;import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.PreDestroy;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@RestController
@RequestMapping("/pro")
public class CpuProblemController {// 添加退出标志private volatile boolean running = true;// 创建线程池private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());/*** 死循环:模拟 CPU 占满*/@PostMapping("/deadLoop")public void deadLoop() {// 启动多个线程,每个线程执行死循环for (int i = 0; i < Runtime.getRuntime().availableProcessors(); i++) {executorService.submit(() -> {while (running) {// 死循环,模拟高 CPU 使用率System.out.println("=======死循环=========");// 加入计算密集型任务for (int j = 0; j < 1000000; j++) {Math.sin(j); // 计算密集型操作}}});}}@PreDestroypublic void stop() {// 服务关闭时触发退出running = false;executorService.shutdownNow(); // 关闭线程池}
}

4.2 不合理递归(栈溢出与CPU飙升)

问题代码

public class RecursionController {public int faultyRecursion(int n) {return n + faultyRecursion(n - 1);  // 无终止条件 → 无限递归}
}

解决方案

public class RecursionController {public int safeRecursion(int n) {if (n <= 0) {  // 添加递归终止条件return 0;}return n + safeRecursion(n - 1);}
}

4.3 线程池未正确关闭(资源泄漏)

问题代码

@RestController
public class ThreadController {private ExecutorService executor = Executors.newFixedThreadPool(10);@GetMapping("/task")public String submitTask() {executor.submit(() -> {while (true) {  // 线程池任务未终止// 长时间运行的任务}});return "Task submitted!";}// 未重写destroy方法关闭线程池 → 线程泄漏
}

解决方案

@RestController
public class ThreadController {private ExecutorService executor = Executors.newFixedThreadPool(10);@GetMapping("/task")public String submitTask() {executor.submit(() -> {while (!Thread.currentThread().isInterrupted()) {  // 检查中断状态// 可中断的任务逻辑}});return "Task submitted!";}@PreDestroypublic void shutdown() {executor.shutdownNow();  // 服务关闭时终止线程池}
}

4.4 锁竞争(线程阻塞与自旋)

问题代码

public class LockCompetitionController {private final Object lock = new Object();public void highCpuMethod() {synchronized (lock) {// 长时间持有锁(如复杂计算或IO操作)try {Thread.sleep(10000);  // 模拟耗时操作} catch (InterruptedException e) {e.printStackTrace();}}}
}

解决方案

public class LockCompetitionDemo {private final Object lock = new Object();public void optimizedMethod() {// 缩小锁范围,只锁必要部分heavyCalculation();  // 将非线程安全操作移到锁外synchronized (lock) {// 仅保护共享资源}}private void heavyCalculation() {// 复杂计算逻辑}
}

4.5 频繁GC(内存泄漏导致CPU飙升)

问题代码

public class MemoryLeakDemo {private static List<byte[]> cache = new ArrayList<>();@GetMapping("/leak")public void leakMemory() {while (true) {cache.add(new byte[1024 * 1024]);  // 不断添加数据 → 触发Full GC}}
}

解决方案

public class MemoryLeakDemo {private static final int MAX_CACHE_SIZE = 100;private static List<byte[]> cache = new ArrayList<>();@GetMapping("/safe")public void safeMethod() {if (cache.size() >= MAX_CACHE_SIZE) {cache.clear();  // 定期清理缓存}cache.add(new byte[1024 * 1024]);}
}

5. 总结与预防

  1. 代码审查:重点关注循环、递归、线程池和锁的使用。
  2. 压测与监控:使用JMeter模拟高并发,通过Arthas实时监控CPU。
  3. 防御式编程:对递归添加终止条件,对循环添加超时机制。
  4. 工具辅助:利用jvisualvmasync-profiler进行性能分析。

希望这篇文章对你有所帮助!如果觉得不错,别忘了点赞收藏哦!

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

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

相关文章

机器学习扫盲系列(2)- 深入浅出“反向传播”-1

系列文章目录 机器学习扫盲系列&#xff08;1&#xff09;- 序 机器学习扫盲系列&#xff08;2&#xff09;- 深入浅出“反向传播”-1 文章目录 前言一、神经网络的本质二、线性问题解析解的不可行性梯度下降与随机梯度下降链式法则 三、非线性问题激活函数 前言 反向传播(Ba…

LabVIEW 线性拟合

该 LabVIEW 程序实现了 线性拟合&#xff08;Linear Fit&#xff09;&#xff0c;用于计算给定一组数据点的斜率&#xff08;Slope&#xff09;和截距&#xff08;Intercept&#xff09;&#xff0c;并将结果可视化于 XY Graph 中。本案例适用于数据拟合、实验数据分析、传感器…

XSS漏洞靶场---(复现)

XSS漏洞靶场—&#xff08;复现&#xff09; 反射型 XSS 的特点是攻击者诱导用户点击包含恶意脚本的 URL&#xff0c;服务器接收到请求后将恶意脚本反射回响应页面&#xff0c;浏览器执行该脚本从而造成攻击&#xff0c;恶意脚本不会在服务器端存储。 Level 1(反射型XSS) 此漏…

优选算法系列(2.滑动窗口 _ 上)

目录 解法⼀&#xff08;暴力求解&#xff09;&#xff08;不会超时&#xff0c;可以通过&#xff09;&#xff1a;一.长度最小的子数组&#xff08;medium&#xff09; 题目链接209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 代码&#…

ELK(Elasticsearch、Logstash、Kbana)安装及Spring应用

Elasticsearch安装及Spring应用 一、引言二、基本概念1.索引&#xff08;Index&#xff09;2.类型&#xff08;Type&#xff09;3.文档&#xff08;Document&#xff09;4.分片&#xff08;Shard&#xff09;5.副本&#xff08;Replica&#xff09; 二、ELK搭建1.创建挂载的文件…

Redis,从数据结构到集群的知识总结

Redis基础部分 2. 数据结构 redis底层使用C语言实现&#xff0c;这里主要分析底层数据结构 2.1 动态字符串(SDS) 由于C底层的字符串数组一旦遇到’\0’就会认为这个字符串数组已经结束&#xff0c;意味着无法存储二进制数据&#xff08;如图片、音频等&#xff09;&#xff…

【redis】Jedis 操作 Redis 基础指令(下)

列表操作 lpush/rpush 和 lpop/rpop 将一个或者多个元素从左/右侧放入&#xff08;头/尾插&#xff09;到 list 中 依次头插 从 list 左/右侧取出元素&#xff08;即头/尾删&#xff09; public static void test1(Jedis jedis) { jedis.flushAll(); long n jedis.lpush(…

基于消失点标定前视相机外参

1. 消失点 艺术家&工程师在纸上表现立体图时,常用一种透视法,这种方法源于人们的视觉经验:近大远小,且平行的直线都消失于无穷远处同一个点。就像我们观察两条平行的铁轨时会觉得他们相交于远处的一点,我们把这个点称为消失点。 图1 铁轨组成的消失点 2. 在标定中的应…

TypeScript接口 interface 高级用法完全解析

TypeScript接口 interface 高级用法完全解析 mindmaproot(TypeScript接口高级应用)基础强化可选属性只读属性函数类型高级类型索引签名继承与合并泛型约束设计模式策略模式工厂模式适配器模式工程实践声明合并类型守卫装饰器集成一、接口核心机制深度解析 1.1 类型兼容性原理 …

Vue3 Pinia $subscribe localStorage的用法 Store的组合式写法

Vue3 Pinia $subscribe 可以用来监视Stroe数据的变化 localStorage的用法 localStorage中只能存字符串&#xff0c;所有对象要选转成json字符串 定义store时&#xff0c;从localStorage中读取数据talkList可能是字符串也可能是空数组 Store的组合式写法 直接使用reactiv…

新版AndroidStudio / IDEA上传项目到Gitee

目录 1.Gitee创建仓库 2.填写仓库的信息 3.创建成功后复制仓库的地址 4.检查AndroidStudio是否配置Git 5.点击测试 6.之后Create Git Repository 7.添加到本地仓库 8.提交项目 9.添加上传仓库的地址 10.上传成功 11.去Gitee上刷新检查 1.Gitee创建仓库 2.填写仓库的…

用 Vue 3.5 TypeScript 重新开发3年前甘特图的核心组件

回顾 3年前曾经用 Vue 2.0 开发了一个甘特图组件&#xff0c;如今3年过去了&#xff0c;计划使用Vue 3.5 TypeScript 把组件重新开发&#xff0c;有机会的话再开发一个React版本。 关于之前的组件以前文章 Vue 2.0 甘特图组件 下面录屏是是 用 Vue 3.5 TypeScript 开发的目前…

C语言【数据结构】:时间复杂度和空间复杂度.详解

引言 详细介绍什么是时间复杂度和空间复杂度。 前言&#xff1a;为什么要学习时间复杂度和空间复杂度 算法在编写成可执行程序后&#xff0c;运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏&#xff0c;一般是从时间和空间两个维度来衡量的&#xff0c;即时…

Matlab 基于专家pid控制的时滞系统

1、内容简介 Matlab 185-基于专家pid控制的时滞系统 可以交流、咨询、答疑 2、内容说明 略 在处理时滞系统&#xff08;Time Delay Systems&#xff09;时&#xff0c;使用传统的PID控制可能会面临挑战&#xff0c;因为时滞会导致系统的不稳定或性能下降。专家PID控制通过结…

MyBatis源码分析のSql执行流程

文章目录 前言一、准备工作1.1、newExecutor 二、执行Sql2.1、getMappedStatement2.2、query 三、Cache装饰器的执行时机四、补充总结 前言 本篇主要介绍MyBatis解析配置文件完成后&#xff0c;执行sql的相关逻辑&#xff1a; public class Main {public static void main(Str…

【MySQL】数据库基础

目录 一、什么是数据库1.1 为什么要有数据库1.2 数据库的本质是什么1.3 在Linux下看一下数据库 二、主流数据库三、基本使用3.1 连接服务器3.2 服务器&#xff0c;数据库&#xff0c;表关系 四、MySQL架构五、SQL分类六、存储引擎6.1 存储引擎是什么6.2 查看存储引擎6.3 存储引…

算是解决可以访问github但无法clone的问题

本文的前提是使用了**且可以正常访问github 查看代理的端口 将其配置到git 首先查看git配置 git config --list然后添加配置&#xff0c;我这边使用的是Hiddfy默认的端口是12334&#xff0c;如果是clash应该是7890 git config --global http.proxy 127.0.0.1:12334其他 删除…

SpringBoot第三站:配置嵌入式服务器使用外置的Servlet容器

目录 1. 配置嵌入式服务器 1.1 如何定制和修改Servlet容器的相关配置 1.server.port8080 2. server.context-path/tx 3. server.tomcat.uri-encodingUTF-8 1.2 注册Servlet三大组件【Servlet&#xff0c;Filter&#xff0c;Listener】 1. servlet 2. filter 3. 监听器…

AdaLoRA 参数 配置:CAUSAL_LM“ 表示因果语言模型任务

AdaLoRA 参数 配置:CAUSAL_LM" 表示因果语言模型任务 config = AdaLoraConfig( init_r=16, # 增加 LoRA 矩阵的初始秩 lora_alpha=32, target_modules=[“q_proj”, “v_proj”], lora_dropout=0.1, bias=“none”, task_type=“CAUSAL_LM” ) 整体功能概述 AdaLoraCon…

IP 协议

文章目录 IP 协议概述数据包格式首部校验和实例分析实例一 分片抓包分析参考 本文为笔者学习以太网对网上资料归纳整理所做的笔记&#xff0c;文末均附有参考链接&#xff0c;如侵权&#xff0c;请联系删除。 IP 协议 概述 IP 协议是 TCP/IP 协议簇中的核心协议&#xff0c;也…