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

springboot优雅停机无法关闭进程,kill无法停止springboot必须kill -9,springboot线程池使用

背景最近项目在jenkins部署的时候发现部署很慢,查看部署日志发现kill命令执行后应用pid还存在,导致必须在60秒等待期后kill -9杀死springboot进程

应用环境

  • springboot
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.6.3</version>
</dependency>
  • springcloud
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2021.0.1.0</version><type>pom</type><scope>import</scope>
</dependency>
  • 监控
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId><version>2.6.3</version>
</dependency>

原因分析

  • 通过将全部日志调整为debug级别,观察到有个定时任务线程在不断执行,例子如下
@SpringBootApplication
@MapperScan("com.test.test.mapper")
public class TestApplication implements CommandLineRunner {static ScheduledExecutorService executor;public static void main(String[] args) {executor = Executors.newScheduledThreadPool(1);SpringApplication.run(TestApplication.class, args);}private static void run(ScheduledExecutorService executor) {executor.scheduleAtFixedRate(() -> {System.out.println("run");}, 0, 1, TimeUnit.SECONDS);@Overridepublic void run(String... args) throws Exception {run(executor);}
}

上述代码中,由于线程定义默认是非守护线程,执行优雅停机后,在用户线程停止后,非守护线程不会自动停止
在这里插入图片描述

在这里插入图片描述

解决办法

  1. 定义为守护线程
    对于非业务逻辑,例如监控数据上传,日志记录,这样做非常方便,但对于系统业务,这么做会导致未执行完成任务被丢弃。
  2. 将线程池定义为springbean,交予spring容器管理其生命周期
@SpringBootApplication
@MapperScan("com.test.test.mapper")
public class TestApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}private static void run(ScheduledExecutorService executor) {executor.scheduleAtFixedRate(() -> {System.out.println("run");}, 0, 1, TimeUnit.SECONDS);}@Beanpublic ScheduledExecutorService executor() {return Executors.newScheduledThreadPool(1);}@Overridepublic void run(String... args) throws Exception {ScheduledExecutorService executor = SpringUtil.getBean(ScheduledExecutorService.class);run(executor);}
}

效果
在这里插入图片描述弊端:此类方式中,由于线程池的工作线程属于非守护线程,应用会等待所有任务执行完成后才关闭。由于容器已经关闭,数据库连接池已经释放,这时候任务再获取spring容器内容会报错,因此这种方案只适用于用户日志记录,监控等非业务功能,效果如下:

@SpringBootApplication
@MapperScan("com.test.test.mapper")
@Slf4j
public class TestApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}private static void run(ExecutorService executor) {executor.execute(() -> {log.info("=====start");try {TimeUnit.SECONDS.sleep(25);User user = SpringUtil.getBean(IUserService.class).findById(10L);log.info("用户信息:" + user);} catch (Exception ex) {ex.printStackTrace();}log.info("=========end");});}@Beanpublic ExecutorService executor() {return new ThreadPoolExecutor(10, 10, 10, TimeUnit.SECONDS,new ArrayBlockingQueue<>(1),r -> {Thread thread =new Thread(r);return thread;},new ThreadPoolExecutor.DiscardOldestPolicy());}@Overridepublic void run(String... args) throws Exception {ExecutorService executor = SpringUtil.getBean(ExecutorService.class);run(executor);}
}

在这里插入图片描述

3.使用spring提供的ThreadPoolTaskExecutor线程池

@SpringBootApplication
@MapperScan("com.test.test.mapper")
@Slf4j
public class TestApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}private static void run(ThreadPoolTaskExecutor executor) {executor.execute(() -> {log.info("=====start");try {TimeUnit.SECONDS.sleep(25);User user = SpringUtil.getBean(IUserService.class).findById(10L);log.info("用户信息:" + user);} catch (Exception ex) {ex.printStackTrace();}log.info("=========end");});}@Beanpublic ThreadPoolTaskExecutor executor() {int core = Runtime.getRuntime().availableProcessors();ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(core > 3 ? core >> 1 : core);int maxSize = core + 2;executor.setMaxPoolSize(maxSize);//使用同步队列,避免任务进入等待队列排队导致耗时过长executor.setQueueCapacity(0);executor.setKeepAliveSeconds(30);executor.setWaitForTasksToCompleteOnShutdown(true);executor.setAwaitTerminationSeconds(25);executor.setThreadNamePrefix("async-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;}@Overridepublic void run(String... args) throws Exception {ThreadPoolTaskExecutor executor = SpringUtil.getBean(ThreadPoolTaskExecutor.class);run(executor);}
}

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
从上图可以看到,应用会等待线程池任务执行完毕后才选择优雅关闭,因此对于异步业务任务,ThreadPoolTaskExecutor才是首选。
spring已经内置了ThreadPoolTaskExecutor 线程池实例,我们可以尝试修改其配置参数,简化代码来尝试,例如:
在这里插入图片描述

spring:task:execution:pool:queue-capacity: 0core-size: 2max-size: 16keep-alive: 30sthread-name-prefix: 'async-'shutdown:await-termination: trueawait-termination-period: 25s
@SpringBootApplication
@MapperScan("com.test.test.mapper")
@Slf4j
public class TestApplication implements CommandLineRunner {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}private static void run(ThreadPoolTaskExecutor executor) {executor.execute(() -> {log.info("=====start");try {TimeUnit.SECONDS.sleep(25);User user = SpringUtil.getBean(IUserService.class).findById(10L);log.info("用户信息:" + user);} catch (Exception ex) {ex.printStackTrace();}log.info("=========end");});}@Overridepublic void run(String... args) throws Exception {ThreadPoolTaskExecutor executor = SpringUtil.getBean(ThreadPoolTaskExecutor.class);run(executor);}
}

效果与上述手动创建效果一样,但是内置的ThreadPoolTaskExecutor线程池无法通过配置修改拒绝策略rejectedExecutionHandler,队列满了之后默认是AbortPolicy,会丢弃加入的任务并抛异常,spring内置此线程池的初衷在于为定时任务使用,例如@Scheduled。
在这里插入图片描述
在这里插入图片描述

相关文章:

springboot优雅停机无法关闭进程,kill无法停止springboot必须kill -9,springboot线程池使用

背景最近项目在jenkins部署的时候发现部署很慢&#xff0c;查看部署日志发现kill命令执行后应用pid还存在&#xff0c;导致必须在60秒等待期后kill -9杀死springboot进程 应用环境 springboot <dependency><groupId>org.springframework.boot</groupId>&l…...

【系统架构设计师-2015年真题】案例分析-答案及详解

更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【材料1】问题1问题2【材料2】问题1问题2问题3【材料3】问题1问题2问题3【材料4】问题1问题2问题3【材料5】问题1问题2问题3【材料1】 阅读以下关于软件架构评估的说明,在答题纸上回答问题1和问题2。 【说明】某软件…...

MongoDB设置系统服务启动教程

1、编辑mongodb.service文件 将MongoDB设置成系统服务&#xff0c;就可以通过systemctl进行启动停止重启&#xff0c;在目录/etc/systemd/system下编写mongodb.service文件&#xff1a; [Unit] DescriptionMongoDB Database Server Documentationhttps://www.mongodb.com/docs…...

mysql学习教程,从入门到精通,MySQL WHERE 子句(10)

1、SQL WHERE 子句 在本教程中&#xff0c;您将学习如何使用SQL从表中选择特定记录。 根据条件选择记录 在上一章中&#xff0c;我们学习了如何从表或表列中获取所有记录。但是&#xff0c;在现实世界中&#xff0c;我们通常只需要选择&#xff0c;更新或删除满足某些条件的那…...

设计模式】Listener模式和Visitor模式的区别

文章目录 前言一、介绍Listener模式Visitor模式 二、代码实现2.1 Listener模式的Java实现2.2Listener模式的Go实现2.3Visitor模式的Java实现2.4Visitor模式的Go实现 三、总结 前言 在软件设计中&#xff0c;设计模式是解决特定问题的通用解决方案。Listener模式和Visitor模式是…...

基于事件序列的数据获取

Data Get 31670 /S Update 2 AI_PC 3Mins /次 Import "Hggw" PI Data AABB020240908_115221_31781 AABB020240908_115521_31781 AABB020240908_115821_31781 1、From PIdata Copy 2 AI PC 2、AI PC UI Chart & Logic OK NG Pump&#xff1a;&#x…...

太速科技-基于XC7Z100+AD9361的双收双发无线电射频板卡

基于XC7Z100AD9361的双收双发无线电射频板卡 一、板卡概述 基于XC7Z100AD9361的双收双发无线电射频板卡是基于Xilinx ZYNQ FPGA和ADI的无线收发芯片AD9361开发的专用功能板卡&#xff0c;用于4G小基站&#xff0c;无线图传&#xff0c;数据收发等领域。 二、板卡…...

探索UWB技术的独特优势:实现高精度定位

UWB定位技术是一种利用无线信号进行精确位置定位的技术&#xff0c;它利用超宽带无线电信号通过测量信号的到达时间、相位差和信号能量等参数来确定物体的精确位置。 UWB定位技术具有多种优势&#xff0c;首先&#xff0c;它具有较高的定位精度&#xff0c;可实现毫米级的精确…...

软件安装攻略:Sublime Text 下载安装和使用教程

Sublime Text 下载安装和使用教程 Sublime Text是一个流行的跨平台文本编辑器&#xff0c;它具有以下一些主要功能和特点&#xff1a; &#xff08;1&#xff09;简洁的界面和快速的速度&#xff1a;Sublime Text拥有简约干净的界面&#xff0c;启动和响应速度很快。 &#…...

ip地址为什么要轮换

在网络世界中&#xff0c;IP地址是设备与互联网通信的身份证。然而&#xff0c;单一的IP地址可能会因为各种原因而需要轮换。IP轮换是指在一定时间内更换正在使用的IP地址&#xff0c;这一策略在多种网络应用中发挥着重要作用。本文将探讨IP地址轮换的原因、其带来的优势以及实…...

C++ 继承【一篇让你学会继承】

1. 继承的概念及定义 1.1 继承的概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特征的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序设计的层次结构&…...

DeviceNet网关HT3S-DNS-MDN读取七星华创CS310空气流量计数据应用案例

七星华创流量计CS310系列 (MODBUS RTU) 通过DeviceNet网关HT3S-DNS-MDN 与台达DVP系列的PLC进行交换数据应用案例 一、概述 本文主要介绍使用HI-TOP网关 HT3S-DNS-MDN在台达DVP系列 PLC和七星华创CS310流量计之间进行数据交换。 解决的问题&#xff1a;台达DVP系列如何通过…...

Smartbi体验中心新增系列Demo,用户体验更丰富

为进一步提升用户体验&#xff0c;让大家更直观地了解Smartbi产品在数据分析方面的功能优势&#xff0c;Smartbi体验中心近期新增了一系列Demo。这些更新旨在优化产品操作流程&#xff0c;并为用户提供更多真实场景下的应用参考。接下来&#xff0c;我们一起简要浏览此次体验中…...

Kubernetes 与 springboot集成

Kubernetes 与 Spring Boot 集成详解 Kubernetes&#xff08;简称 K8s&#xff09;是一个用于自动化部署、扩展和管理容器化应用的开源平台&#xff0c;而 Spring Boot 是 Java 开发领域中非常流行的微服务框架。将这两者结合&#xff0c;可以充分利用 Kubernetes 强大的容器编…...

以太网传输出现不分包

最近对手件反馈,在传输文件的时候,我们这边发包太快,导致对手件网络出现了拥塞,把他们程序给搞死了。他们抓了一下他们收到的包,发现我们发送的数据包都大于了MTU设置的值。现在被要求更改。 排查方法:为什么我们发送的数据包会大于MTU的值。 可能性一:配置了Dont Fra…...

[实践应用] 深度学习之激活函数

文章总览&#xff1a;YuanDaiMa2048博客文章总览 深度学习之激活函数 激活函数基本概念分类常见的激活函数2. Tanh/双曲正切激活函数3. ReLU激活函数4. Softmax激活函数 PyTorch中如何使用1. 线性激活函数2. 非线性激活函数SigmoidTanhReLULeaky ReLUParametric ReLU (PReLU) 使…...

Java基础之数组

文章地址&#xff1a;Java基础之数组 码农爱刷题 为计算机编程爱好者和从业人士提供技术总结和分享 &#xff01;为前行者蓄力&#xff0c;为后来者探路&#xff01;...

基于SpringBoot+Vue的智慧自习室预约管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…...

pptpd配置文件/etc/pptpd.conf详解

正文共&#xff1a;1111 字 2 图&#xff0c;预估阅读时间&#xff1a;1 分钟 如果要在Linux系统配置PPTP&#xff08;Point-to-Point Tunneling Protocol&#xff0c;点到点隧道协议&#xff09;VPN&#xff0c;一般是使用pptpd软件。pptpd命令通常从配置文件/etc/pptpd.conf中…...

springboot对数据库进行备份+对一个文件夹内的文件按时间排序,只保留最近的8个文件

首先&#xff0c;对数据库进行备份&#xff0c;用到的命令&#xff1a; mysqldump --opt -h 192.168.1.200 --userroot --passwordxxx --result-fileE://data//20240911141400.sql --default-character-setutf8 xxx&#xff08;数据库名&#xff09; 直接上代码 配置文件部分…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...