Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Boot 内嵌容器 Tomcat / Undertow / Jetty 优雅停机实现

Spring Boot 内嵌容器 Tomcat / Undertow / Jetty 优雅停机实现

作者头像
精讲java
发布于 2018-07-03 09:29:55
发布于 2018-07-03 09:29:55
2.5K00
代码可运行
举报
文章被收录于专栏:平凡文摘平凡文摘
运行总次数:0
代码可运行

Spring Boot 在关闭时,如果有请求没有响应完,在不同的容器会出现不同的结果,例如,在 Tomcat 和 Undertow 中会出现中断异常,那么就有可能对业务造成影响。所以,优雅停机非常有必要性,目前官方是没有提供很好的策略来实现。

Each SpringApplication registers a shutdown hook with the JVM to ensure that the ApplicationContext closes gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface or the @PreDestroy annotation) can be used.

Spring Boot Application 在接收到停机信号后,可以通过 DisposableBean 接口 、 @PreDestroy 注解 或者 ContextClosedEvent 事件来处理优雅停机的相关逻辑。

版本信息

Spring Boot 版本: 2.0.0.RELEASE

Tomcat 优雅停机

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    /**
     * 用于接受 shutdown 事件
     */
    @Bean
    public GracefulShutdown gracefulShutdown() {
        return new GracefulShutdown();
    }

    @Bean
    public ServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        tomcat.addConnectorCustomizers(gracefulShutdown());
        return tomcat;
    }

    /**
     * 优雅关闭 Spring Boot
     */
    private class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
        private final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);
        private volatile Connector connector;
        private final int waitTime = 30;
        @Override
        public void customize(Connector connector) {
            this.connector = connector;
        }
        @Override
        public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
            this.connector.pause();
            Executor executor = this.connector.getProtocolHandler().getExecutor();
            if (executor instanceof ThreadPoolExecutor) {
                try {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                    threadPoolExecutor.shutdown();
                    if (!threadPoolExecutor.awaitTermination(waitTime, TimeUnit.SECONDS)) {
                        log.warn("Tomcat thread pool did not shut down gracefully within " + waitTime + " seconds. Proceeding with forceful shutdown");
                    }
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

}

Undertow 优雅停机

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    /**
     * 优雅关闭 Spring Boot
     */
    @Component
    public class GracefulShutdown implements ApplicationListener<ContextClosedEvent> {

        @Autowired
        private GracefulShutdownWrapper gracefulShutdownWrapper;

        @Autowired
        private ServletWebServerApplicationContext context;

        @Override
        public void onApplicationEvent(ContextClosedEvent contextClosedEvent){
            gracefulShutdownWrapper.getGracefulShutdownHandler().shutdown();
            try {
                UndertowServletWebServer webServer = (UndertowServletWebServer)context.getWebServer();
                Field field = webServer.getClass().getDeclaredField("undertow");
                field.setAccessible(true);
                Undertow undertow = (Undertow) field.get(webServer);
                List<Undertow.ListenerInfo> listenerInfo = undertow.getListenerInfo();
                Undertow.ListenerInfo listener = listenerInfo.get(0);
                ConnectorStatistics connectorStatistics = listener.getConnectorStatistics();
                while (connectorStatistics.getActiveConnections() > 0){}
            }catch (Exception e){
                // Application Shutdown
            }
        }
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
public class GracefulShutdownWrapper implements HandlerWrapper{

    private GracefulShutdownHandler gracefulShutdownHandler;

    @Override
    public HttpHandler wrap(HttpHandler handler) {
        if(gracefulShutdownHandler == null) {
            this.gracefulShutdownHandler = new GracefulShutdownHandler(handler);
        }
        return gracefulShutdownHandler;
    }

    public GracefulShutdownHandler getGracefulShutdownHandler() {
        return gracefulShutdownHandler;
    }

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component
@AllArgsConstructor
public class UndertowExtraConfiguration {

    private final GracefulShutdownWrapper gracefulShutdownWrapper;

    @Bean
    public UndertowServletWebServerFactory servletWebServerFactory() {
        UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
        factory.addDeploymentInfoCustomizers(deploymentInfo -> deploymentInfo.addOuterHandlerChainWrapper(gracefulShutdownWrapper));
        factory.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_STATISTICS, true));
        return factory;
    }

}

Jetty 优雅停机

默认支持所有请求完毕后再关闭,缺点:客户端接收不到响应,有待改进!

转载声明:本文转载自「精讲JAVA」。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-05-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 平凡文摘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring Boot 1.X和2.X优雅重启实战
在重启之前首先发送重启命令到endpoint,或者用kill 进程ID的方式,千万不要用kill -9。
猿天地
2018/07/25
1.5K0
Spring Boot 1.X和2.X优雅重启实战
项目在重新发布的过程中,如果有的请求时间比较长,还没执行完成,此时重启的话就会导致请求中断,影响业务功能,优雅重启可以保证在停止的时候,不接收外部的新的请求,等待未完成的请求执行完成,这样可以保证数据的完整性。
后端老鸟
2020/04/12
1.1K0
Spring Boot 1.X和2.X优雅重启实战
如何优雅地停止 Spring Boot 应用?
首先来介绍下什么是优雅地停止,简而言之,就是对应用进程发送停止指令之后,能保证正在执行的业务操作不受影响,可以继续完成已有请求的处理,但是停止接受新请求。
武培轩
2020/06/09
1.2K0
如何优雅地停止 Spring Boot 应用?
玩转 Spring Boot 原理篇(内嵌Tomcat实现原理&优雅停机源码剖析)
玩转 Spring Boot 集成篇(Actuator、Spring Boot Admin)
一猿小讲
2022/04/12
2K0
玩转 Spring Boot 原理篇(内嵌Tomcat实现原理&优雅停机源码剖析)
面试官:SpringBoot如何优雅停机?
优雅停机(Graceful Shutdown) 是指在服务器需要关闭或重启时,能够先处理完当前正在进行的请求,然后再停止服务的操作。
磊哥
2024/03/18
1K0
Spring Boot 系列:最新版优雅停机详解
目前Spring Boot已经发展到了2.3.4.RELEASE,伴随着2.3版本的到来,优雅停机机制也更加完善了。
鲁大猿
2020/10/14
1.2K0
Springboot内置容器原理
springboot强大的地方就是,相比于传统spring架构,省去了很多繁杂的配置,其中一个就是springboot支持了内置容器,启动的时候框架层面帮我们初始化和启动容器,我们更多的关心代码和业务逻辑实现即可,那么它是如何支持内置容器的,以及内置容器是如何初始化和启动的,本篇文章将展开详细分析。
叔牙
2022/01/20
1.8K0
Springboot内置容器原理
CTO 说了,再发现谁用 kill -9 关闭程序就开除!
kill可将指定的信息送至程序。预设的信息为SIGTERM(15),可将指定程序终止。若仍无法终止该程序,可使用SIGKILL(9)信息尝试强制删除程序。程序或工作的编号可利用ps指令或jobs指令查看。
终码一生
2022/04/14
4200
CTO 说了,再发现谁用 kill -9 关闭程序就开除!
Spring Boot 2.3 新特性优雅停机详解
当我们流量请求到此接口执行业务逻辑的时候,若服务端此时执行关机 (kill),spring boot 默认情况会直接关闭容器(tomcat 等),导致此业务逻辑执行失败。在一些业务场景下:会出现数据不一致的情况,事务逻辑不会回滚。
冷冷
2020/05/18
1.7K0
还在使用kill -9 pid结束spring boot项目吗?那你已经落伍了!
kill可将指定的信息送至程序。预设的信息为SIGTERM(15),可将指定程序终止。若仍无法终止该程序,可使用SIGKILL(9)信息尝试强制删除程序。程序或工作的编号可利用ps指令或jobs指令查看(这段话来自菜鸟教程)。
肉眼品世界
2021/01/25
9450
还在使用kill -9 pid结束spring boot项目吗?那你已经落伍了!
Spring Boot如何启动嵌入式Tomcat?
Spring Boot在内部启动了一个嵌入式Web容器。 Tomcat是组件化设计,所以就是启动这些组件。
JavaEdge
2021/10/18
1.8K0
SpringBoot嵌入式Tomcat的自动配置原理
我们知道SpringBoot的自动装配的秘密在org.springframework.boot.autoconfigure包下的spring.factories文件中,而嵌入Tomcat的原理就在这个文件中加载的一个配置类:org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
Java学习录
2019/09/27
1.3K0
重学SpringBoot3-ServletWebServerFactoryAutoConfiguration类
在Spring Boot 3中,ServletWebServerFactoryAutoConfiguration 类扮演着至关重要的角色,它负责自动配置内嵌的 Servlet 容器,例如 Tomcat、Jetty 或 Undertow。这种自动配置能力是 Spring Boot 框架的核心特性之一,它极大地简化了 Spring 应用的开发和部署过程。本文将深入探讨ServletWebServerFactoryAutoConfiguration 类的工作原理、配置方式以及如何通过它来定制内嵌Servlet容器。
CoderJia
2024/10/18
1990
重学SpringBoot3-ServletWebServerFactoryAutoConfiguration类
这样优化Spring Boot,启动速度快到飞起!
微服务用到一时爽,没用好就呵呵啦,特别是对于服务拆分没有把控好业务边界、拆分粒度过大等问题,某些 Spring Boot 启动速度太慢了,可能你也会有这种体验,这里将探索一下关于 Spring Boot 启动速度优化的一些方方面面。
艾小仙
2022/12/05
3K0
这样优化Spring Boot,启动速度快到飞起!
总在说 Spring Boot 内置了 Tomcat 启动,那它的原理你说的清楚吗?
来自:cnblogs.com/sword-successful/p/11383723.html
良月柒
2020/09/23
7010
总在说 Spring Boot 内置了 Tomcat 启动,那它的原理你说的清楚吗?
详述 Spring Boot 中内嵌 Tomcat 的实现原理
对于一个 Spring Boot Web 工程来说,一个主要的依赖标志就是有spring-boot-starter-web这个starter,spring-boot-starter-web模块在 Spring Boot 中其实并没有代码存在,只是在pom.xml中携带了一些依赖,包括web、webmvc和tomcat等:
CG国斌
2020/06/04
6.1K0
springboot如何启动内置tomcat?(源码详解)
传统项目为了启动,会放在tomcat下面,那么springboot为何不需要放在tomcat启动呢??因为springboot有内置tomcat启动项目,这篇文章从源码分析springboot如何启动内置tomcat。
keying
2022/07/29
1.3K0
springboot如何启动内置tomcat?(源码详解)
拒绝 kill -9, SpringBoot 优雅停机详解!文末赠书!
这次Spring Boot 2.3对于这个常见场景做了配置化实现,下面就来一起看看如何使用吧!
Guide哥
2020/10/30
2.3K0
拒绝 kill -9, SpringBoot 优雅停机详解!文末赠书!
SpringBoot 2.3 新特性之优雅停机,这波操作太秀了!
当我们流量请求到此接口执行业务逻辑的时候,若服务端此时执行关机 (kill),spring boot 默认情况会直接关闭容器(tomcat 等),导致此业务逻辑执行失败。在一些业务场景下:会出现数据不一致的情况,事务逻辑不会回滚。
程序员小猿
2021/01/19
2.1K0
SpringBoot 2.3 新特性之优雅停机,这波操作太秀了!
面试被问:Spring Boot中Tomcat是如何启动的?
Spring Boot一个非常突出的优点就是不需要我们额外再部署Servlet容器,它内置了多种容器的支持。我们可以通过配置来指定我们需要的容器。
业余草
2020/09/01
1.3K0
面试被问:Spring Boot中Tomcat是如何启动的?
相关推荐
Spring Boot 1.X和2.X优雅重启实战
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验