本文为原创文章。欢迎任何形式的转载,但请务必注明出处 冷冷https://lltx.github.io。git
先来一段简单的代码,以下:github
@RestController public class DemoController { @GetMapping("/demo") public String demo() throws InterruptedException { // 模拟业务耗时处理流程 Thread.sleep(20 * 1000L); return "hello"; } } 复制代码
当咱们流量请求到此接口执行业务逻辑的时候,若服务端此时执行关机 (kill),spring boot 默认状况会直接关闭容器(tomcat 等),致使此业务逻辑执行失败。在一些业务场景下:会出现数据不一致的状况,事务逻辑不会回滚。web
在最新的 spring boot 2.3 版本,内置此功能,不须要再自行扩展容器线程池来处理, 目前 spring boot 嵌入式支持的 web 服务器(Jetty、Reactor Netty、Tomcat 和 Undertow)以及反应式和基于 Servlet 的 web 应用程序都支持优雅停机功能。 咱们来看下如何使用:spring
当使用server.shutdown=graceful
启用时,在 web 容器关闭时,web 服务器将再也不接收新请求,并将等待活动请求完成的缓冲期。tomcat
/** * Configuration for shutting down a {@link WebServer}. * * @author Andy Wilkinson * @since 2.3.0 */ public enum Shutdown { /** * 优雅停机 (限期停机) * */ GRACEFUL, /** * 当即停机 */ IMMEDIATE; } 复制代码
timeout-per-shutdown-phase
配置2020-05-17 18:28:28.940 INFO 60341 --- [extShutdownHook] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete 2020-05-17 18:28:45.923 INFO 60341 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete 复制代码
- 关于此处执行kill -2 而不是 kill -9
//ApplicationContext @Override public void registerShutdownHook() { if (this.shutdownHook == null) { // No shutdown hook registered yet. this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) { @Override public void run() { synchronized (startupShutdownMonitor) { doClose(); } } }; Runtime.getRuntime().addShutdownHook(this.shutdownHook); } } 复制代码
- 经过 actuate 端点实现优雅停机
POST 请求 /actuator/shutdown 便可执行优雅关机。bash
源码解析服务器
@Endpoint(id = "shutdown", enableByDefault = false) public class ShutdownEndpoint implements ApplicationContextAware { @WriteOperation public Map<String, String> shutdown() { Thread thread = new Thread(this::performShutdown); thread.setContextClassLoader(getClass().getClassLoader()); thread.start(); } private void performShutdown() { try { Thread.sleep(500L); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } // 此处close 逻辑和上边 shutdownhook 的处理同样 this.context.close(); } } 复制代码
- 不一样 web 容器优雅停机行为区别
容器停机行为取决于具体的 web 容器行为markdown
web 容器名称 | 行为说明 |
---|---|
tomcat 9.0.33+ | 中止接收请求,客户端新请求等待超时。 |
Reactor Netty | 中止接收请求,客户端新请求等待超时。 |
Undertow | 中止接收请求,客户端新请求直接返回 503。 |