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

线程池导致的 shutdown失败的完整排查过程

SpringBoot 中有一种方式可以优雅地关闭应用程序。

(优雅停机是指关闭应用程序时,在规定的超时时间范围内,允许进行中的请求完成,拒绝新的请求进入。 这将使应用在请求处理方面保持一致,即没有未处理请求,每一个请求都被处理(完成或拒绝)

配置如下

yml server: port: 8888 shutdown: graceful management: endpoint: shutdown: enabled: true endpoints: web: exposure: include: shutdown
xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>

现象

直接调用 localhost:8888/actuator/shutdown 即可关闭应用程序。但是在调用某个业务后,再调用 shutdown 的 api,发现实际 shutdown 确实在执行,但是最终并没有把 pid 给 kill 掉,应用程序依然在运行。

第一怀疑就是认为这个程序执行后,还有什么资源没有被关闭掉,导致 springboot 认为应用程序还在运行,从而没有执行关闭操作。

排查过程

执行脚本

shell 生成线程快照 jstack -l pid > threads.txt # 查询非守护进程(因为非守护线程会阻止 JVM 退出) -v 表示反向排除 grep -n '" ' threads2.txt | grep -v daemon
  • 所有线程信息
  • 非守护线程信息

在里面发现了一段 关于 "pool-X-thread-Y"的线程信息,这个 ThreadPoolExecutor 出来的线程,处于等待中,其他的都是额外框架的线程信息或者 jvm 的,只有"pool-X-thread-Y"属于额外的。

less "pool-4-thread-1" #230 prio=5 os_prio=31 cpu=0.21ms elapsed=252.08s tid=0x00000001642cf800 nid=0x9a07 waiting on condition [0x000000017aaf6000] java.lang.Thread.State: WAITING (parking) at jdk.internal.misc.Unsafe.park(java.base@17.0.13/Native Method) - parking to wait for <0x0000000701e8af30> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(java.base@17.0.13/LockSupport.java:341) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionNode.block(java.base@17.0.13/AbstractQueuedSynchronizer.java:506) at java.util.concurrent.ForkJoinPool.unmanagedBlock(java.base@17.0.13/ForkJoinPool.java:3465) at java.util.concurrent.ForkJoinPool.managedBlock(java.base@17.0.13/ForkJoinPool.java:3436) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@17.0.13/AbstractQueuedSynchronizer.java:1630) at java.util.concurrent.ArrayBlockingQueue.take(java.base@17.0.13/ArrayBlockingQueue.java:420) at java.util.concurrent.ThreadPoolExecutor.getTask(java.base@17.0.13/ThreadPoolExecutor.java:1062) at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.13/ThreadPoolExecutor.java:1122) at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.13/ThreadPoolExecutor.java:635) at java.lang.Thread.run(java.base@17.0.13/Thread.java:840) Locked ownable synchronizers: - None
  • ThreadPoolExecutor 默认线程名称源码

有了这个排查方向,去项目里面查找关于ThreadPoolExecutor的代码。

最终发现一句关于线程池的声明代码。从代码来看,虽然 XxxConfig 类上加了 @Configuration 注解,受到 spring 管理,但是 XXX_EXECUTOR 这个线程池是静态变量, 并没有受到 spring 管理,所以 springboot 在执行 shutdown 的时候,并不会关闭这个线程池,导致应用程序没有被关闭。

java @Configuration public class XxxConfig { public static final ThreadPoolExecutor XXX_EXECUTOR = new ThreadPoolExecutor(20, 20, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10000), new ThreadPoolExecutor.CallerRunsPolicy()); }

最终解决方案

建议将 XXX_EXECUTOR 这个线程池改为 spring 管理的 bean,如下所示:

java @Configuration public class XxxConfig { @Bean("xxxExecutor") public ThreadPoolExecutor xxxExecutor() { //示例 demo return new ThreadPoolExecutor(20, 20, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10000), new ThreadPoolExecutor.CallerRunsPolicy()); } }
http://www.cnnetsun.cn/news/27314.html

相关文章:

  • Windows验机
  • 别让孩子视力提早“透支” ,这份护眼指南请收好
  • 儿童青少年近视干预科学指引,破解家长近视防控焦虑
  • 解析 .NET 核心基石:CTS、CLS 与 CLR 的核心价值与协同作用
  • Selinux权限的检测
  • 常见报错org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): org.example.dem
  • 甲骨文AI投资支出激增致股价创24年最大跌幅
  • TinyMCE4粘贴word超链接自动解析域名
  • TinyMCE6处理微信公众号音频视频嵌入
  • 昇腾 Ascend 自定义算子开发全攻略:从 TBE DSL 到 AICPU,打通 AI 加速最后一公里
  • 当电机开始“唱歌“:NVH工程师的降噪日常
  • AI界的“经济适用男“!80亿参数小模型完胜GPT-5,成本降低70%,CSDN程序员必藏的智能调度方案
  • FPGA教程系列-Vivado Aurora 8B/10B 例程解读
  • 227827827
  • MCU的启动流程你了解么?
  • 逻辑回归(Logistic Regression)进行多分类的实战
  • RNN(循环神经网络)原理
  • 人机协同重构创作生态——生成式AI赋能内容产业的变革与思考
  • Java 小白求职者在互联网大厂的面试实录:从 Spring Boot 到微服务架构
  • V助手舆情分析智能体:重塑舆情分析,从“人找信息”到“信息为人”
  • 连接2026:十款远程控制软件真实力横评与选择指南
  • 计算机毕业设计springboot基于Spark++Vue.js的学生管理系统 Spark+Vue 高校学生综合信息管理平台 基于 SpringBoot+Spark+Vue 的全链路学生事务中心
  • JavaScript 集合操作的哈希碰撞:攻击者如何利用特殊 Key 导致 Map/Set 性能降级到 O(N)
  • 为什么 C盘空间会莫名其妙减少(即使没装新软件)?
  • 17、深入理解 Linux 文件系统机制与结构
  • 29、Linux 软件使用与故障排除指南
  • 从入门到转行:网络安全自学与跳槽的终极建议
  • 网络安全小白自学之路,别拜师了,求人不如求己_网络安全小白怎么自学
  • 从系统运维到网络安全工程师,8个月转行真实经验分享!
  • 算法系列(Algorithm)- 快速排序