当前位置: 首页 > 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; 直接上代码 配置文件部分…...

【软考中级攻略站】-软件设计师(4)-计算机网络基础

计算机网络的分类 1. 局域网&#xff08;Local Area Network, LAN&#xff09; 局域网是指在一个较小的地理区域内连接的计算机网络&#xff0c;比如学校的机房、公司的办公室或者家里的Wi-Fi网络。在这个网络内的计算机可以直接相互通信&#xff0c;速度很快&#xff0c;延迟…...

Android以及IoT设备传感器软件开发总结

1 传感器选型 1.1 传感器选型 6 axis&#xff1a;Bosch BMI160&#xff08;比较差&#xff09;&#xff0c;InvenSense MPU6050&#xff08;DMP&#xff09;&#xff0c;ST LSM6Dxx Acc: Freescale MMA7450L (MicroMachined Accelerometer/MC Multi-Axis, iMX31), Kionix KXSD9…...

Vue2/Vue3中编程式路由导航实践总结

【1】Vue2编程式路由导航 ① router.push 除了使用 <router-link> 创建 a 标签来定义导航链接&#xff0c;我们还可以借助 router 的实例方法&#xff0c;通过编写代码来实现。 router.push(location, onComplete?, onAbort?)注意&#xff1a;在 Vue 实例内部&#…...

【nginx】ngx_http_proxy_connect_module 正向代理

50.65无法访问 服务器, (403 错误) 50.196 可以访问服务器。 那么,配置65 通过196 访问。 需要一个nginx作为代理 【nginx】搭配okhttp 配置反向代理 发送原生的nginx是不支持okhttp的CONNECT请求的。 大神竟然给出了一个java工程 GINX编译ngx_http_proxy_connect_module及做…...

单考一个OCP认证?还是OCP和OCM认证都要考?

​ Oracle的OCP认证是数据库行业非常经典的一个认证&#xff0c;从事数据库行业的人都建考一个 Oracle OCP 认证。 OCP认证内容包括&#xff1a; OCA部分&#xff1a;数据库基础知识、SQL 语言使用、基本的数据库管理技能等&#xff0c;如数据库安装与配置、理解数据库架构、…...

在Spring官网查看Springboot与Java的版本对应关系

查看Spring Boot与Java的版本对应关系&#xff0c;可以按照以下步骤操作&#xff1a; 访问Spring官方网站&#xff0c;进入Spring Boot项目页面。可以通过点击菜单中的“Projects”&#xff0c;然后选择“Spring Boot”来访问。Spring | Home 在Spring Boot的LEARN页签中&…...

HarmonyOS学习(十二)——数据管理(一)分布式数据

文章目录 1、分布式数据服务概述2、KV数据模型&#xff08;键值对数据库&#xff09;3、分布式数据服务的约束和限制4、接口说明5、分布式数据服务开发步骤5.1、导入模块5.2、构造分布式数据库管理类实例5.3、获取、创建分布式数据库5.4、订阅分布式数据库的数据变化5.5、插入数…...

3D GS 测试自己的数据

环境配置 win11 vs2019cuda11.8driver522.06python3.10pytorch 2.4.0colmap3.8&#xff08;可选&#xff0c;用于将图像生成点云&#xff09; 安装 1 minicodagit 略 2 vs2019 在装cuda前安装&#xff0c; 选择c桌面开发即可&#xff0c; 环境变量path中配置C:\Program…...

攻防世界 supersqli

supersqli 一般sql语句的题都是先判断&#xff0c;经过测试&#xff0c;是单引号注入 999 union select database(),2#可以发现很多关键字都被过滤了select&#xff0c;所以联合查询&#xff0c;报错注入&#xff0c;布尔和时间盲注都不能用了&#xff0c;可以想到堆叠注入。…...

OceanBase 运维管理工具 OCP 4.x 升级:聚焦高可用、易用性及可观测性

可视化的管控平台&#xff0c;对 OceanBase 这类的分布式数据库及大规模数据的运维管理来说&#xff0c;是提升运维效率与数据库管理水平的重要工具。OceanBase 运维管理工具 OCP 作为专为OceanBase数据库设计的企业级全生命周期管理平台&#xff0c;为用户提供了全面的数据库可…...