什么是优雅停机

先来一段简单的代码,如下:

@RestController
public class DemoController {
@GetMapping("/demo")
public String demo() throws InterruptedException {
// 模拟业务耗时处理流程
Thread.sleep(20 * 1000L);
return "hello";
}
}

当我们流量请求到此接口执行业务逻辑的时候,若服务端此时执行关机 (kill),spring boot 默认情况会直接关闭容器(tomcat 等),导致此业务逻辑执行失败。在一些业务场景下:会出现数据不一致的情况,事务逻辑不会回滚。

graceful shutdown

在最新的 spring boot 2.3 版本,内置此功能,不需要再自行扩展容器线程池来处理,

目前 spring boot 嵌入式支持的 web 服务器(Jetty、Reactor Netty、Tomcat 和 Undertow)以及反应式和基于 Servlet 的 web 应用程序都支持优雅停机功能。 我们来看下如何使用:

当使用server.shutdown=graceful启用时,在 web 容器关闭时,web 服务器将不再接收新请求,并将等待活动请求完成的缓冲期。

配置体验

此处支持的 shutdown 行为,我们看下 源码枚举如下:
/**
* Configuration for shutting down a {@link WebServer}.
*
* @author Andy Wilkinson
* @since 2.3.0
*/
public enum Shutdown { /**
* 优雅停机 (限期停机)
*
*/
GRACEFUL, /**
* 立即停机
*/
IMMEDIATE; }
缓冲期 timeout-per-shutdown-phase 配置
  • 默认时间为 30S, 意味着最大等待 30S,超时候无论线程任务是否执行完毕都会停机处理,一定要合理合理设置。

效果体验

    1. 请求服务端接口

    1. 执行关闭应用

    1. 服务端接到关闭指令
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
    1. 接口请求执行完成

相关知识

  1. 关于此处执行kill -2 而不是 kill -9
  • kill -2 相当于快捷键 Ctrl + C 会触发 Java 的 ShutdownHook 事件处理(优雅停机或者一些后置处理可参考以下源码)
//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);
}
}
  • kill -9,暴力美学强制杀死进程,不会执行 ShutdownHook
  1. 通过 actuate 端点实现优雅停机

POST 请求 /actuator/shutdown 即可执行优雅关机。

源码解析

@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();
}
}
  1. 不同 web 容器优雅停机行为区别

容器停机行为取决于具体的 web 容器行为

web 容器名称 行为说明
tomcat 9.0.33+ 停止接收请求,客户端新请求等待超时。
Reactor Netty 停止接收请求,客户端新请求等待超时。
Undertow 停止接收请求,客户端新请求直接返回 503。

项目推荐: Spring Cloud 、Spring Security OAuth2的RBAC权限管理系统 欢迎关注

Spring Boot 2.3 新特性优雅停机详解的更多相关文章

  1. Spring Boot 系列:最新版优雅停机详解

    爱生活,爱编码,本文已收录架构技术专栏关注这个喜欢分享的地方. 开源项目: 分布式监控(Gitee GVP最有价值开源项目 ):https://gitee.com/sanjiankethree/cub ...

  2. Spring Boot 2(一):Spring Boot 2.0新特性

    Spring Boot 2(一):Spring Boot 2.0新特性 Spring Boot依赖于Spring,而Spring Cloud又依赖于Spring Boot,因此Spring Boot2 ...

  3. spring boot actuator端点高级进阶metris指标详解、git配置详解、自定义扩展详解

    https://www.cnblogs.com/duanxz/p/3508267.html 前言 接着上一篇<Springboot Actuator之一:执行器Actuator入门介绍>a ...

  4. Spring Boot 2.0 新特性和发展方向

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  5. 【2.0新特性】Spring Boot 2.0新特性

    以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Java 6 和 7 不再支持. 内嵌容器包结构调整 为了支持reactive使用场景,内嵌的容器包结构被重构了 ...

  6. Spring Boot实践——Spring Boot 2.0 新特性和发展方向

    出自:https://mp.weixin.qq.com/s/EWmuzsgHueHcSB0WH-3AQw 以Java 8 为基准 Spring Boot 2.0 要求Java 版本必须8以上, Jav ...

  7. Spring Boot 2.0 新特性

    这是一篇总结文章,主要收集 Spring Boot 2.0 相对于 Spring Boot 1.x 的新特性,本章节并不提供实践性质的源代码.在 Spring Boot 系列文章中会持续退出实践章节. ...

  8. 原创 Spring Boot 2.3 新特性分层JAR

    背景 在我们实际生产容器化部署过程中,往往会遇到 Docker 镜像很大,部署发布很慢的情况 影响 docker 镜像大小的因素,主要有以下三个方面: 基础镜像的大小 .尽量选择 aphine 作为基 ...

  9. 『Spring Boot 2.4新特性』减少95%内存占用

    节省 95%的内存占用,减少 80%的启动耗时. GraalVM 是一种高性能的虚拟机,它可以显著的提高程序的性能和运行效率,非常适合微服务.最近比较火的 Java 框架 Quarkus 默认支持 G ...

随机推荐

  1. AtCoder Regular Contest 113

    比赛地址 A(暴力) 题目链接 题目: 给出\(K\),求出满足\(A\times B\times C\le K\)的\((A,B,C)\)对数 解析: 将C移动到等式右边,得到\(A\times B ...

  2. Vue框架-组件的概念及使用

    目录 一.Vue组件 1. 组件分类 1.1 根组件 1.2 局部组件 1.3 全局组件 2. 组件的特点 3. 如何创建组件 4. 组件的数据局部化 5. 组件传参·父传子 6. 组件传参·子传父 ...

  3. 《Asp.Net Core3 + Vue3入坑教程》-Net Core项目搭建与Swagger配置步骤

    简介 <Asp.Net Core3 + Vue3入坑教程> 此教程仅适合新手入门或者前后端分离尝试者.可以根据图文一步一步进操作编码也可以选择直接查看源码.每一篇文章都有对应的源码 教程后 ...

  4. 基于docker搭建gitlab

    一.概述 GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目. 它拥有与Github类似的功能,能够浏览 ...

  5. 如何理解JavaScript中的函数

    转: 如何理解JavaScript中的函数 JS中的函数简介 JS中的函数是一种通过调用来完成具体业务的一段代码块.最核心的目的是将可重复执行的操作进行封装,然后供调用方无限制的调用. JS中的函数的 ...

  6. c++ vector对象

    下面随笔讲解c++ vector对象. vector对象 为什么需要vector? 封装任何类型的动态数组,自动创建和删除. 数组下标越界检查. 封装的如ArrayOfPoints也提供了类似功能,但 ...

  7. MySQL全面瓦解24:构建高性能索引(策略篇)

    学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...

  8. Maven基础&&Spring框架阶段常用工具类整理

    常用工具类 1.密码加密工具类: package com.itheima.utils; import java.security.MessageDigest; import sun.misc.BASE ...

  9. 进阶宝典一|SqlServer数据库自动备份设置

    很多人都没机会接触到数据库备份,经常操作的要么是数据库管理员,要么是项目负责人.那是不是说数据库备份就不用学了? 不,其实作为开发人员应该要了解数据备份,数据备份的手段有很多:软件备份.脚本备份.其他 ...

  10. 如何报告FreeBSD 的bug?

    https://bugs.freebsd.org/bugzilla/ 注册个账号即可,请使用英语,把程序在不同程序上的运行结果列出来即可- ​​​​ 注意标记架构,如果有log还请一并附上,英语差可以 ...