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

springboot项目如何优雅停机

文章目录

    • 前言
    • kill -9 pid的危害
    • 如何优雅的停机
      • 理论步骤
      • 优雅方式
        • 1、kill -15 pid 命令停机
        • 2、ApplicationContext close停机
        • 3、actuator shutdown 停机
        • 4、ApplicationListener 监听延时停机

前言

相信很多同学都会用Kill -9 PID来杀死进程,如果用在我们微服务项目里面,突然杀死进程会有什么后果?有没有其他的方式优雅的停机呢?今天,我们就来讨论下kill -9 pid 这个命令对微服务项目的影响,以及如何优雅的停机的问题。

kill -9 pid的危害

kill -9 属于暴利删除,直接杀死进程。对于微服务系统而言,直接判了死刑,直接从系统层面对进程进行了结束。微服务中的线程,根本没有反应的机会直接香消玉损。

比如前端发起的订单请求,后端springboot项目中的线程正在处理订单数据的保存。此时如果kill -9 pid 将微服务进程杀死,后端将不会有任何响应请求的机会,页面请求会立即中断出现异常情况。虽然一般对于后端事务数据库都会回滚,但是,页面出现异常毕竟会让用户体验度下降。

如何优雅的停机

理论步骤

1、停止接收请求和内部线程
2、判断是否有线程正在执行
3、等待正在执行的线程执行完毕
4、停止tomcat容器

优雅方式

1、kill -15 pid 命令停机

项目增加测试入口:

/*** 停机 测试* kill -15* kill -9* @return a* @author senfel* @date 2023/5/13 17:37*/
@GetMapping("test")
public void test(){log.error("测试方法进入开始===========");try {Thread.sleep(100000);} catch (InterruptedException e) {e.printStackTrace();}log.error("测试方法执行结束===========");
}

服务启动项目

[root@devops-01 tmp]# nohup java -jar demo.jar &
[11] 43451
[root@devops-01 tmp]# nohup: ignoring input and appending output to ‘nohup.out’

页面访问地址后服务器用kill -15 PID结束进程

[root@devops-01 tmp]# kill -15 43451

查看日志:
在这里插入图片描述

居然报错了,但是测试日志都打印出来了。为什么会报错呢?这就和sleep这个方法有关了,在线程休眠期间,当调用线程的interrupt方法的时候会导致sleep抛出异常,这里很明显就是kill -15 这个命令会让程序马上调用线程的interrupt方法,目的是为了让线程停止,虽然让线程停止,但线程什么时候停止还是线程自己决定。

kill -15 pid 会等待线程执行完并拒绝新的请求,如果有线程睡眠会抛出java.lang.InterruptedException异常。

2、ApplicationContext close停机

项目增加测试代码:

/*** shutdown* @author senfel* @version 1.0* @date 2023/5/13 18:04*/
@RestController
@Slf4j
public class ShutDownController implements ApplicationContextAware {private ApplicationContext context;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.context = applicationContext;}/*** 停机 ConfigurableApplicationContext方式* @return a* @author senfel* @date 2023/5/13 17:36*/@PostMapping(value = "shutdown")public void shutdown(){ConfigurableApplicationContext cyx = (ConfigurableApplicationContext) context;cyx.close();}
}

启动项目

[root@devops-01 tmp]# nohup java -jar demo.jar &
[15] 44001
[root@devops-01 tmp]# nohup: ignoring input and appending output to ‘nohup.out’

调用测试方法后,调用上下文主动停机接口/shutdown
查看服务日志:
在这里插入图片描述

同样的日志信息,表示调用上下文停机后会等待线程执行完并拒绝新的请求,如果有线程睡眠会抛出java.lang.InterruptedException异常。

3、actuator shutdown 停机

引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

配置yml

management:endpoints:web:exposure:include: health,shutdownendpoint:shutdown:enabled: true

这种方式是通过引入依赖的方式停止服务,actuator提供了很多接口,比如健康检查,基本信息等等,
我们也可以使用他来优雅的停机。

调用接口测试//actuator/shutdown
查看日志:
在这里插入图片描述

查看日志同样是停机后会等待线程执行完并拒绝新的请求,如果有线程睡眠会抛出java.lang.InterruptedException异常。只不过页面会有提示,更加的友好。

在这里插入图片描述

4、ApplicationListener 监听延时停机

以上三种都是直接打断睡眠线程,那么有没有一种方式在阻断新请求的同时,让睡眠线程睡眠完成优雅停机呢?
有点,我们的ApplicationListener 可以监听到服务关闭事件,覆写事件并延时即可。

增加监听代码:

/*** GracefulShutdown* @author senfel* @version 1.0* @date 2023/5/13 19:40*/
@Slf4j
@Component
public class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {private volatile Connector connector;@Overridepublic void customize(Connector connector) {this.connector = connector;}@Overridepublic void onApplicationEvent(ContextClosedEvent event) {this.connector.pause();Executor executor = this.connector.getProtocolHandler().getExecutor();if (executor instanceof ThreadPoolExecutor) {try {ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;threadPoolExecutor.shutdown();if (!threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS)) {log.error("Tomcat thread pool did not shut down gracefully within 30 seconds. Proceeding with forceful shutdown");}} catch (InterruptedException ex) {Thread.currentThread().interrupt();}}}
}

先请求带有睡眠代码的接口,然后停机,查看日志:
在这里插入图片描述

http://www.lryc.cn/news/93220.html

相关文章:

  • springboot mybatis-plus 代码生成工具
  • 超全、超详细的Redis学习笔记总结
  • Day05 04-MySQL分库分表介绍
  • 基于SpringBoot+vue的毕业生信息招聘平台设计和实现
  • git一定要学会,加油
  • TVM面试题
  • CSS相关面试题
  • 6.11总结
  • Hazel游戏引擎(008-009)事件系统
  • 【C++】 STL(上)STL简述、STL容器
  • 【002 基础知识】什么是原子操作?
  • English Learning - L3 作业打卡 Lesson5 Day32 2023.6.5 周一
  • 深度学习应用篇-自然语言处理-命名实体识别[9]:BiLSTM+CRF实现命名实体识别、实体、关系、属性抽取实战项目合集(含智能标注)【上篇】
  • 腾讯安全SOC+荣获“鑫智奖”,助力金融业数智化转型
  • Python绘制气泡图示例
  • 数学建模经历-程序人生
  • 数字电子电路绪论
  • 电脑丢失dll文件一键修复需要什么软件?快速修复dll文件的方法
  • 你知道微信的转账是可以退回的吗
  • 【链表Part01】| 203.移除链表元素、707.设计链表、206.反转链表
  • 如何使用Postman生成curl?
  • CSS灯光效果,背景黑金效果
  • 这里推荐几个前端icon网站(动图网站)
  • 【图神经网络】用PyG实现图机器学习的可解释性
  • HarmonyOS ArkTS Ability内页面的跳转和数据传递
  • MySQL 8.0.29 instant DDL 数据腐化问题分析
  • Haproxy搭建负载均衡
  • SpringBoot:SpringBoot启动加载过程 ④
  • 抽象轻松JavaScript
  • 深入理解CSS字符转义行为