【框架】Spring Boot: 实现优雅退出

2018.11.18

文章目录

    • 前言
    • 方法
      • 方法一:Actuator的Endpoint机制[^1]
      • 方法二:使用`ApplicationContext#close()`方法
      • 方法三:`@PreDestroy` + `kill `

前言

要求某个基于Spring Boot的调度器,能实现优雅退出,使得退出时正在运行时的作业能进行必要的回滚操作。为此,翻译某技术博客的总结1

方法

每个Spring应用都会在JVM里注册一个shutdown hook1,以保证ApplicationContext能实现优雅退出。以下的方法都是基于这一原理进行实现的。

方法一:Actuator的Endpoint机制1

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-actuatorartifactId>
dependency>

默认配置下,shutdown端点是关闭的,需要在application.properties里配置:

management.endpoint.shutdown.enabled=true

Actuator的端点,支持通过JMX或HTTP进行远程访问。而shutdown默认配置下是不支持HTTP进行Web访问的,所以使用HTTP请求进行关闭,还需要配置:

management.endpoints.web.exposure.include=shutdown

最后,配合使用对应的URL就能让Spring Boot应用优雅退出:

curl -X POST localhost:port/actuator/shutdown

方法二:使用ApplicationContext#close()方法

ApplicationContext#close()亦能实现优雅退出,但要使得当前application context退出,就需要一个入口,从外部接收到退出的信号。一种方法就是上述的Endpoint端点,另一种方法适用于Spring MVC的Web应用,就是定制一个Controller实现ApplicationContextAware接口如下:

@RestController
public class ShutdownController implements ApplicationContextAware {
    private ApplicationContext context;
    
    @PostMapping("/shutdownContext")
    public void shutdownContext() {
        ((ConfigurableApplicationContext) context).close();
    }
    @Override
    public void setApplicationContext(ApplicationContext ctx) throws BeansException {
        this.context = ctx;    
    }
}

同样地,配合使用对应的URL就能让Spring Boot应用优雅退出:

curl -X POST localhost:port/shutdownContext

方法三:@PreDestroy + kill

如果项目不是Spring MVC,又不想引入Actuator,可以直接采用ctrl + c或kill 的方式。因为Spring应用在JVM里注册了一个shutdown hook,所以只要能接收到退出的信号(ctrl + c或kill ,而kill -9 不行),那么应用就能正常地优雅退出。如果项目是通过nohup java -jar project.jar &方式启动的,那么就建议使用kill 命令,给应用发送一个TERM信号,就能正常优雅退出。@PreDestroy注解允许方法完成必要的退出工作。

获取pid的方式可使用如下两种:

  1. Bash shell
ps -ef | grep project.jar | awk '{print $2}'
  1. Java代码
SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE);
app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid"));
app.run();

  1. Baeldung about Spring Boot shutdown ↩︎ ↩︎ ↩︎

  2. Actuator Endpoints
    Actuator提供了Endpoint端点,可能用于对Spring Boot应用进行监控和交互。其中有一个shutdown端点,就是用于优雅退出的。使用Actuator的端点,首先需要配置Actuator相关依赖2: ↩︎

你可能感兴趣的:(Spring,Boot,原理,框架)