什么是优雅停机

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

@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. ViewPager 高度自适应

    public class ContentViewPager extends ViewPager { public ContentViewPager(Context context) { super(c ...

  2. Python 学习笔记(3)

    Python 文件I/O 读取键盘输入: Python提供了两个内置函数从标准输入读入一行文本,默认的标准输入是键盘: 1. raw_input #函数从标准输入读取一个行,并返回一个字符串(去掉结尾 ...

  3. 后端程序员之路 27、LogStash

    访谈与书评:<LogStash,使日志管理更简单>http://www.infoq.com/cn/articles/review-the-logstash-book/ [Logstash] ...

  4. “蚂蚁牙黑”太火,想玩就用ModelArts做一个!

    摘要:本文将介绍如何借力一站式 AI 开发平台,"傻瓜式"操作实现生成"蚂蚁牙黑"小视频. 作者:华为云EI专家胡琦 一夜之间,朋友圈都在"蚂蚁牙黑& ...

  5. 如何读写拥有命名空间xmlns 属性的Xml文件(C#实现)

    我们在进行C#项目Xml读写开发时经常遇到一些读写问题,今天我要介绍的是遇到多个命名空间xmlns属性时如何读写此类文件. 比如下面这个Xml文件: <?xml version="1. ...

  6. 数据结构-PHP 线段树的实现

    转: 数据结构-PHP 线段树的实现 1.线段树介绍 线段树是基于区间的统计查询,线段树是一种 二叉搜索树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点.使用线段树可以快速的查 ...

  7. 剑指 Offer 12. 矩阵中的路径 + 递归 + 深搜 + 字符串问题

    剑指 Offer 12. 矩阵中的路径 题目链接 题目类似于迷宫的搜索. 需要注意的是,需要首先判断起始搜索的位置,可能有多个起点,都需要一一尝试. 每轮迭代的时候记得将是否遍历标记数组还原为未遍历的 ...

  8. React函数式组件和类组件[Dan]

    一篇对Dan的 How Are Function Components Different from Classes? 一文的个人阅读总结,内容来自于此.强烈推荐阅读 Dan Abramov.的博客. ...

  9. shell脚本,mysql数据库的备份-2[mysqldump]

    # 数据库IPIP=127.0.0.1# 数据库端口PORT=3306# 数据库用户USER=root# 数据库密码PASSWORD=****# 要备份的数据库TARGET_DB=database_n ...

  10. ts装饰器的用法,基于express创建Controller等装饰器

    TS TypeScript 是一种由微软开发的自由和开源的编程语言.它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类 型和基于类的面向对象编程. TypeScript 扩 ...