SpringBoot实现优雅停机的流程步骤

 更新时间:2024年03月19日 08:41:40   作者:Java中文社群  
优雅停机(Graceful Shutdown) 是指在服务器需要关闭或重启时,能够先处理完当前正在进行的请求,然后再停止服务的操作,本文给大家介绍了SpringBoot实现优雅停机的流程步骤,需要的朋友可以参考下

前言

优雅停机(Graceful Shutdown) 是指在服务器需要关闭或重启时,能够先处理完当前正在进行的请求,然后再停止服务的操作。

优雅停机的实现步骤主要分为以下几步:

  • 停止接收新的请求:首先,系统会停止接受新的请求,这样就不会有新的任务被添加到任务队列中。
  • 处理当前请求:系统会继续处理当前已经在处理中的请求,确保这些请求能够正常完成。这通常涉及到等待正在执行的任务完成,如处理HTTP请求、数据库操作等。
  • 释放资源:在请求处理完成后,系统会释放所有已分配的资源,如关闭数据库连接、断开网络连接等。
  • 关闭服务:最后,当所有请求都处理完毕且资源都已释放后,系统会安全地关闭服务。

0.SpringBoot如何实现优雅停机?

优雅停机的实现步骤分为以下两步:

  • 使用合理的 kill 命令,给 Spring Boot 项目发送优雅停机指令。
  • 开启 Spring Boot 优雅停机/自定义 Spring Boot 优雅停机的实现。

1.合理杀死进程

在 Linux 中 kill 杀死进程的常用命令有以下这些:

  • kill -2 pid:向指定 pid 发送 SIGINT 中断信号,等同于 ctrl+c。也就说,不仅当前进程会收到该信号,而且它的子进程也会收到终止的命令。
  • kill -9 pid:向指定 pid 发送 SIGKILL 立即终止信号。程序不能捕获该信号,最粗暴最快速结束程序的方法。
  • kill -15 pid:向指定 pid 发送 SIGTERM 终止信号。信号会被当前进程接收到,但它的子进程不会收到,如果当前进程被 kill 掉,它的的子进程的父进程将变成 init 进程 (init 进程是那个 pid 为 1 的进程)。
  • kill pid:等同于 kill 15 pid。

因此,在以上命令中,我们不能使用“kill -9”来杀死进程,使用“kill”杀死进程即可

2.设置SpringBoot优雅停机

在 Spring Boot 2.3.0 之后,可以通过配置设置开启 Spring Boot 的优雅停机功能,如下所示:

# 开启优雅停机,默认值:immediate 为立即关闭
server.shutdown=graceful

# 设置缓冲期,最大等待时间,默认:30秒
spring.lifecycle.timeout-per-shutdown-phase=60s

此时,应用在关闭时,Web 服务器将不再接受新请求,并等待正在进行的请求完成的缓冲时间。

然而,如果是 Spring Boot 2.3.0 之前,就需要自行扩展(线程池)来实现优雅停机了。它的核心实现实现是在系统关闭时会调用 ShutdownHook,然后在 ShutdownHook 中阻塞 Web 容器的线程池,直到所有请求都处理完毕再关闭程序,这样就实现自定义优雅线下了。

但是,不同的 Web 容器(Tomcat、Jetty、Undertow)有不同的自定义优雅停机的方法,以 Tomcat 为例,它的自定义优雅停机实现如下。

2.1 Tomcat 容器关闭代码

public class TomcatGracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
    private volatile Connector connector;

    public void customize(Connector connector) {
        this.connector = connector;
    }

    public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
        this.connector.pause();
        Executor executor = this.connector.getProtocolHandler().getExecutor();
        if (executor instanceof ThreadPoolExecutor) {
            try {
                log.info("Start to shutdown tomcat thread pool");
                ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                threadPoolExecutor.shutdown();
                if (!threadPoolExecutor.awaitTermination(20, TimeUnit.SECONDS)) {
                    log.warn("Tomcat thread pool did not shutdown gracefully within 20 seconds. ");
                }
            } catch (InterruptedException e) {
                log.warn("Fail to shut down tomcat thread pool ", e);
            }
        }
    }
}

2.2 设置 Tomcat 自动装配

@Configuration
@ConditionalOnClass({Servlet.class, Tomcat.class})
public static class TomcatConfiguration {
    @Bean
    public TomcatGracefulShutdown tomcatGracefulShutdown() {
        return new TomcatGracefulShutdown();
    }

    @Bean
    public EmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory(TomcatGracefulShutdown gracefulShutdown) {
        TomcatEmbeddedServletContainerFactory tomcatFactory = new TomcatEmbeddedServletContainerFactory();
        tomcatFactory.addConnectorCustomizers(gracefulShutdown);
        return tomcatFactory;
    }
}

最后

到此这篇关于SpringBoot实现优雅停机的流程步骤的文章就介绍到这了,更多相关SpringBoot优雅停机内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • synchronized底层原理之JVM层面的锁实现细节与流程

    synchronized底层原理之JVM层面的锁实现细节与流程

    本文从JVM底层视角,详细拆解了synchronized的实现逻辑,涵盖锁的存储载体(对象头的MarkWord)、锁的触发指令(monitorenter/monitorexit指令和ACC_SYNCHRONIZED标志位)以及锁的调度机制,感兴趣的朋友跟随小编一起看看吧
    2026-01-01
  • 浅谈Java中GuavaCache返回Null的注意事项

    浅谈Java中GuavaCache返回Null的注意事项

    Guava在实际的Java后端项目中应用的场景还是比较多的,比如限流,缓存,容器操作之类的,本文主要介绍了GuavaCache返回Null的注意事项,感兴趣的可以了解一下
    2021-10-10
  • 两万字详解Java Sring String的常见操作以及StringBuffer StringBuilder的区别

    两万字详解Java Sring String的常见操作以及StringBuffer StringBuilder的区别

    本篇文章带你认识Sring、String的常见操作和StringBuffer 与StringBuilder的区别(字符串详解),对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Java中Properties类的操作实例详解

    Java中Properties类的操作实例详解

    这篇文章主要介绍了Java中Properties类的操作实例详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • java 进程是如何在Linux服务器上进行内存分配的

    java 进程是如何在Linux服务器上进行内存分配的

    这篇文章主要介绍了java 进程是如何在Linux服务器上进行内存分配的,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-11-11
  • java整合SSM框架的图文教程

    java整合SSM框架的图文教程

    下面笔者就为大家分享一篇java整合SSM框架的图文教程,具有很好的参考价值,希望对大家有所帮助。一起跟随笔者过来看看吧
    2017-11-11
  • Gradle的安装和IDEA集成、项目导入的详细教程

    Gradle的安装和IDEA集成、项目导入的详细教程

    这篇文章主要介绍了Gradle的安装和IDEA集成、项目导入的详细教程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • java设计日历可视化的详细步骤记录

    java设计日历可视化的详细步骤记录

    这篇文章主要给大家介绍了关于java设计日历可视化的相关资料,通过自定义的CircleLabel类来突出显示今天的日期,并使用BorderLayout布局管理窗口组件,文章详细描述了各个类和方法的设计思想和实现逻辑,需要的朋友可以参考下
    2024-12-12
  • SpringCloud之注册中心之Nacos负载均衡详解

    SpringCloud之注册中心之Nacos负载均衡详解

    Nacos提供多种负载均衡策略,包括权重、同机房、同地域、同环境等,服务下线和权重配置可以通过Nacos管理界面进行,同时,Nacos使用Raft算法选举Leader节点,若IP地址改变可能会影响Leader选举,配置同集群优先访问可以提高访问速度,通过配置集群名称和负载均衡策略
    2025-03-03
  • Java使用JavaMail API实现原生邮箱发送功能的方法

    Java使用JavaMail API实现原生邮箱发送功能的方法

    文章介绍了如何使用JavaMailAPI在Java后端实现原生邮箱发送功能,包括配置邮件服务器、获取校验码以及解决SSL握手异常的问题,需要的朋友可以参考下
    2026-02-02

最新评论