前言

什么是优雅停机?简单来说就是在对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响。应用接收到停止指令之后的步骤应该是,停止接收访问请求,等待已经接收到的请求处理完成,并能成功返回,这时才真正停止应用。本文主要描述的是SpringBoot中优雅停机的几种方式。

方式一:使用Springboot配置

前提:Tomcat版本在9.0.33以上或SpingBoot版本在2.3以上

Graceful shutdown is supported with all four embedded web servers (Jetty, Reactor Netty, Tomcat, and Undertow) and with both reactive and Servlet-based web applications. It occurs as part of closing the application context and is performed in the earliest phase of stopping SmartLifecycle beans. This stop processing uses a timeout which provides a grace period during which existing requests will be allowed to complete but no new requests will be permitted. The exact way in which new requests are not permitted varies depending on the web server that is being used. Jetty, Reactor Netty, and Tomcat will stop accepting requests at the network layer. Undertow will accept requests but respond immediately with a service unavailable (503) response.

  • 不同服务器有不同的行为:

    • Jetty, Reactor Netty, Tomcat:停止接收请求,客户端新请求超时

    • Undertow:接收请求但回复503

配置

  • 开启优雅关闭:
    • graceful:优雅停机
    • immediate:立即停机
server:
  shutdown: graceful
  • 设置缓冲器(超时后无论线程任务是否执行完毕都会停机处理):
spring:
  lifecycle:
    timeout-per-shutdown-phase: 20s

使用

  • 执行kill -2 $PIDkill -15 $PID
2021-06-29 19:39:51.724  INFO 29534 --- [extShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown        : Commencing graceful shutdown. Waiting for active requests to complete
2021-06-29 19:39:51.732  INFO 29534 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : Graceful shutdown complete

PS:

  1. kill -2 相当于快捷键 Ctrl + C 会触发 Java的 ShutdownHook 事件处理
  2. kill -9,强制杀死进程,不会执行 ShutdownHook

方式二:调用actuator提供的接口

Spring Boot includes a number of additional features to help you monitor and manage your application when you push it to production. You can choose to manage and monitor your application by using HTTP endpoints or with JMX. Auditing, health, and metrics gathering can also be automatically applied to your application.

  • 请求**/actuator/shutdown**执行优雅停机

引入maven依赖

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

配置

management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "shutdown"
  • management.endpoint.shutdown.enabled:是否启动shutdown功能,默认false

  • management.endpoints.web.exposure.include:暴露actuator的shutdown端口

    • 可以把配置中的shutdown换成其他,比如*(全部端点)、health(健康检查)、info(统计)等

使用

  • 发起POST请求至/actuator/shutdown
curl 'http://localhost:8080/actuator/shutdown' -i -X POST

回得到以下结果:

HTTP/1.1 200 OK
Content-Type: application/vnd.spring-boot.actuator.v3+json
Content-Length: 41

{
  "message" : "Shutting down, bye..."
}

服务日志:

2021-06-29 19:39:51.724  INFO 29534 --- [extShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown        : Commencing graceful shutdown. Waiting for active requests to complete
2021-06-29 19:39:51.732  INFO 29534 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown        : Graceful shutdown complete