SpringBoot2.3新特性优雅停机详解

yizhihongxing

SpringBoot2.3新特性优雅停机详解

简介

在以往的项目中,我们在正常停止服务时,往往都是使用kill的方式来停止,这种方式虽然简单,但是可能会导致一些问题,比如程序被强制关闭时,可能会导致正在处理的请求直接中断等问题。SpringBoot2.3中新增了一个优雅停机的功能,可以让我们在停止服务时,更加安全和优雅。

优雅停机的原理

在之前的SpringBoot版本中,当我们使用kill命令关闭程序时,操作系统都是直接向程序发送SIGTERM信号,让程序进行退出。但是在SpringBoot2.3中,程序会在收到SIGTERM信号时,进行优雅停机操作,它的流程如下:

  1. 在收到SIGTERM信号后,程序会停止接收新的请求。
  2. 当所有正在处理的请求处理完毕后,程序会优雅退出。

使用示例

下面是两个使用示例:

示例1:使用默认的优雅停机配置

在SpringBoot2.3中,我们只需要在application.properties配置文件中添加下面的配置,即可使用默认的优雅停机功能:

server.shutdown=graceful

同时,在我们的Java代码中,可以在SpringApplication.run方法中添加下面的内容,来手动触发关闭程序:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        ConfigurableApplicationContext context = application.run(args);

        // 注册关闭钩子
        context.registerShutdownHook();
    }
}

这样,在关闭程序时,程序会自动触发优雅停机操作。

示例2:自定义优雅停机配置

如果需要自定义优雅停机的配置,我们需要创建一个实现了GracefulShutdown接口的类,然后在application.properties配置文件中添加下面的配置:

server.shutdown=graceful
spring.lifecycle.timeout-per-shutdown-phase=30s

其中,GracefulShutdown接口有两个方法,分别是shutdown()getPhase()shutdown()方法中是自定义的优雅关闭逻辑,getPhase()方法则是返回一个数值,表示该关闭操作的阶段。

下面是一个示例:

@Configuration
public class GracefulShutdownConfig {

    @Bean
    public GracefulShutdown gracefulShutdown() {
        return new GracefulShutdown();
    }

    private class GracefulShutdown implements GracefulShutdownCallback, GracefulShutdown {
        private final Logger logger = LoggerFactory.getLogger(GracefulShutdown.class);
        private volatile boolean isShuttingDown = false;
        private final AtomicInteger shutdownCount = new AtomicInteger(0);  // 统计关闭请求次数
        private CountDownLatch shutDownLatch = new CountDownLatch(1);

        @Override
        public void shutdown() {
            if (!this.isShuttingDown) {
                this.isShuttingDown = true;
                logger.info("Shutdown is being called......");

                Thread td = new Thread(() -> {
                    // 判断是否还有未完成的请求
                    int loopCount = 0;
                    while (true) {
                        if(Service.getIsFinished()) {
                            break;
                        }else if(shutdownCount.get() == 1) {
                            Service.finish();
                        }else if(loopCount >= 60) {
                            logger.info("Timeout exit because of 60 loops check finished");
                            Service.finish();
                        }else {
                            logger.info("wait for all services finish up......num of task unfinish : {}", Service.getTaskCount() - Service.getFinishCount());
                            try {
                                Thread.sleep(1000L);
                                loopCount += 1;
                            } catch (InterruptedException e) {
                                logger.error("Close sleep exception {}", e.getMessage());
                            }
                        }
                    }

                    // 关闭服务器
                    shutDownLatch.countDown();
                });
                td.setDaemon(false);
                td.start();
            }

            try {
                shutDownLatch.await(30, TimeUnit.SECONDS);
                logger.info("Shutdown is finished......");
            } catch (InterruptedException e) {
                logger.error("Close Timing out Eclipse processes: ", e);
            }

        }

        @Override
        public int getPhase() {
            return Integer.MAX_VALUE;   // 返回一个较大的数字,保证该操作是最后一步执行
        }

        @Override
        public String toString() {
            return this.getClass().getSimpleName();
        }
    }
}

在该示例中,我们定义了一个GracefulShutdownConfig配置类,其中包含一个实现了GracefulShutdown接口的GracefulShutdown内部类。在shutdown()方法中,我们进行了自定义的关闭逻辑,首先判断程序中是否还有未完成的请求,如果有,则等待请求完成,然后在关闭服务器;如果无未完成的请求,则直接关闭服务器。

getPhase()中,我们返回了一个较大的数字,保证该操作是在其他关闭操作完成后,最后一个执行。

总结

SpringBoot2.3中添加了优雅停机的功能,可以让我们在关闭程序时更加安全和优雅。我们可以使用默认的配置,也可以进行自定义配置。在自定义配置时,我们需要创建一个实现了GracefulShutdown接口的类,在其中编写自己的优雅停机逻辑。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot2.3新特性优雅停机详解 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • FCKeditor JSP版漏洞

    FCKeditor JSP版漏洞(CVE-2009-2265)是一种常见的跨站脚本攻击(XSS)漏洞,攻击者可以在网站页面上注入恶意脚本,从而窃取用户的敏感信息或者控制用户的会话。以下是详细讲解这个漏洞的完整攻略: 漏洞背景 FCKeditor是一个开源的富文本编辑器,其中包含了JSP版,但JSP版在处理文件上传方面存在漏洞。攻击者可以通过构造一个包含特制的…

    Java 2023年6月15日
    00
  • JAVA按字节读取文件的简单实例

    下面是“JAVA按字节读取文件的简单实例”的攻略: 简介 在Java中,可以通过字节流的方式读取文件,即逐个字节地读取文件中的内容。这种方式对于某些特殊情况下的文件操作非常有用。本文将展示Java中如何使用字节流读取文件的简单实例。 步骤 1. 创建File对象 首先,需要创建一个File对象。可以通过File类的构造函数来实现。 File file = n…

    Java 2023年5月19日
    00
  • MT6589平台通话录音时播放提示音给对方功能的具体实现

    要实现“MT6589平台通话录音时播放提示音给对方功能”,需要在两个方面进行修改: 修改系统代码,使得当调用通话录音时,系统能够在录音开始时往话筒播放提示音; 修改通话录音应用程序的源代码,使得当开始录音时,能够调用系统接口往话筒播放提示音。 下面将具体介绍实现这一功能的步骤和示例: 步骤一:修改系统代码 打开系统源代码,找到通话录音相关的文件,例如Audi…

    Java 2023年5月23日
    00
  • Java之JFrame输出Helloworld实例

    Java中,JFrame是一种可用于创建窗口的GUI (图形用户界面) 组件。要创建JFrame输出hello world实例,需要按照以下步骤进行操作: 导入相关库 首先,需要导入javax.swing包,因为它包含用于创建JFrame窗口的类。 import javax.swing.JFrame; 创建一个新的JFrame对象并设置标题 利用JFrame…

    Java 2023年5月24日
    00
  • sql语句中如何将datetime格式的日期转换为yy-mm-dd格式

    要将Datetime格式的日期转换为yy-mm-dd格式,可以使用SQL语句中的CONVERT()函数。具体步骤如下: 使用CONVERT()函数,将Datetime类型的日期转换为Char类型的日期。语法如下: CONVERT(char(10), [Date], 120) 这里需要解释一下,第二个参数[Date]表示输入的Datetime类型的日期。第三个…

    Java 2023年5月19日
    00
  • 详解js的延迟对象、跨域、模板引擎、弹出层、AJAX【附实例下载】

    详解js的延迟对象、跨域、模板引擎、弹出层、AJAX 本文主要介绍 JavaScript 中五个常用的技术点:延迟对象、跨域、模板引擎、弹出层和 AJAX。我们将使用示例来演示这五个技术点的应用。 延迟对象 延迟对象(Deferred Object)是 jQuery 中异步编程的核心概念之一。在 JavaScript 中,通常采用回调函数进行异步编程。而延迟…

    Java 2023年5月19日
    00
  • 一小时迅速入门Mybatis之增删查改篇

    一小时迅速入门Mybatis之增删查改篇 Mybatis是一款优秀的ORM框架,其简单易用,功能强大,得到了广大开发者的喜爱。本文将为大家介绍使用Mybatis进行增删查改的完整攻略。 1. 环境准备 Mybatis需要依赖JDBC驱动和数据库连接池,建议使用Maven进行管理。这里我们以MySQL为例,展示如何配置环境。 首先在pom.xml文件中添加以下…

    Java 2023年5月20日
    00
  • Java中ArrayList集合的常用方法大全

    Java中ArrayList集合的常用方法大全 1. ArrayList简介 ArrayList是Java中最常用的集合之一,它是一个动态的数据结构,就像一个可变长度的数组,可以随时添加和删除元素。它可以存储任何类型的对象,包括基本数据类型的包装类。 2. 创建ArrayList 要使用ArrayList,首先需要在代码中创建它。下面是几种创建ArrayLi…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部