Spring Boot 项目优雅关闭(两种完善解决方案附带示例代码)

前言

Spring Boot 项目优雅关闭常用两种方案,一种是使用kill -2 和 -15 发送程序终止信号,另一种是使用spring-boot-actuator包提供一个优雅下线接口,这两种方案根据自己喜好来,万不得已别用kill -9就行,个人推荐第一种,对于Spring Boot 项目来说两种方法只是入口不同,最终关闭逻辑都是一样的,具体的逻辑会在接下来阐述。

一、Spring Boot 项目优雅关闭核心逻辑

只要是Spring项目无论是何种方法最终都是调用到Spring的AbstractApplicationContext.doClose() 方法来实现优雅关闭,这里介绍的两种方法只是入口不同而已,在后面方案中会详细介绍。

PS:Spring Boot版本 ≥ 2.0
不同版本可能实现不同不过最终都是调用到AbstractApplicationContext.doClose() 方法来实现的关闭。

二、方案原理和实现(这里不包含Tomcat优雅关闭在下面扩展中会有详细介绍)

方案一原理和实现示例(通过kill -2 和 -15 优雅关闭,这种方式SpringBoot是默认支持的)

kill -2 和 -15 是操作系统给该进程发送一个信号通知,告知应用主动关闭,应用可以监听并接收到信号,可以完成一些关闭回收等动作,然后自我停止,这些关闭信号并不是由spring感知,而是由java线程Signal Dispatcher监听,此线程将收到的信号交给JVM,JVM判断信号种类,如果是-2/-15等关闭类型,则交由java.lang.Shutdown完成关闭,关闭前会触发所有的shutdown hookRuntime.getRuntime().addShutdownHook() 可以添加自定义的 shutdown hook

在启动类SpringApplication中会调用自己的refreshContext方法,通过 SpringApplicationShutdownHook.addRuntimeShutdownHook() 方法调用 Runtime.getRuntime().addShutdownHook() 添加自定义的 shutdown hook,在进程接收到kill -2 或 -15 时触发。

在这里插入图片描述
SpringApplicationShutdownHook实现了 Runnable 重写了run 方法,当进程接收到kill -2 或 -15 时触发执行关闭逻辑。
在这里插入图片描述

演示

# 发送一个关闭信号通知
kill -15 pid

在这里插入图片描述
这里可以看到数据源定时任务等工具的关闭日志,还会看到一个线程池的关闭日志,这个后面扩展中会详细说明。

方案二原理和实现示例(通过spring-boot-actuator提供优雅关闭接口)

spring-boot-actuator是一个应用监控框架同时也提供了SpringBoot优雅下线的接口,原理还是一样的最终会调用到AbstractApplicationContext.doClose() 方法来实现的关闭,也可以自己写一个接口去调用AbstractApplicationContext.doClose(),这个有兴趣可以自己实现。

代码实现

  • POM
        <!--    监控 版本同步spring-boot    -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
  • 配置文件
spring:
  lifecycle:
    # 优雅下线超时时间
    timeout-per-shutdown-phase: 1m
# 暴露 shutdown 接口
# 调用 curl -X POST http://127.0.0.1:18080/actuator/shutdown
management:
  server:
    ### 端口
    port: 18080
    ### 允许服务地址
    address: 127.0.0.1
  endpoint:
    ### 是否开启下线 默认关闭
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        ### 暴露接口
        include: shutdown

演示

在这里插入图片描述
这里看到的效果和方案一是一样的,可以看到数据源定时任务等工具的关闭日志,只是执行线程变了,线程池关闭看扩展。

三、扩展

通过 @PreDestroy 注解关闭自定义线程池和其它自定义工具

@PreDestroy是Java规范JSR-250引入的注解,定义了对象的销毁工作,同一期规范中还有注解@Resource,Spring也支持了这些注解,会在Spring提供的一个后置处理器InitDestroyAnnotationBeanPostProcessor中调用的,当Spring容器销毁时会调用到@PreDestroy标记的方法,在这个方法中自行处理关闭逻辑即可。

在这里插入图片描述

优雅关闭内嵌Tomcat

内嵌Tomcat会使用到TomcatWebServerTomcatWebServer提供了一个优雅关闭Tomcat的方法shutDownGracefully,如果不配置默认是直接关闭,需要在配置文件中配置server.shutdown = graceful 开启优雅关闭。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用Spring Boot执行存储过程的示例代码: 1. 首先,在pom.xml文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jdbc</artifactId> </dependency> ``` 2. 接着,在application.properties文件中添加数据库连接配置信息,例如: ``` spring.datasource.url=jdbc:mysql://localhost:3306/mydb spring.datasource.username=myuser spring.datasource.password=mypassword ``` 3. 在Java代码中,创建一个存储过程执行器类,例如: ``` @Component public class StoredProcedureExecutor { @Autowired private JdbcTemplate jdbcTemplate; public void executeStoredProcedure() { jdbcTemplate.execute("CALL my_stored_procedure()"); } } ``` 4. 在需要执行存储过程的位置调用该执行器类的executeStoredProcedure()方法即可,例如: ``` @RestController public class MyController { @Autowired private StoredProcedureExecutor storedProcedureExecutor; @GetMapping("/execute-stored-procedure") public void executeStoredProcedure() { storedProcedureExecutor.executeStoredProcedure(); } } ``` 注意,在这个示例中,我们假设存储过程的名称为my_stored_procedure(),并且它不接受任何参数。如果你需要传递参数给存储过程,可以使用jdbcTemplate.call()方法,例如: ``` jdbcTemplate.call("{CALL my_stored_procedure(?)}", Collections.singletonList("my_parameter")); ``` 这个示例中,我们传递了一个名为my_parameter的参数给存储过程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值