美文网首页
Spring优雅停止服务的实现及原理分析

Spring优雅停止服务的实现及原理分析

作者: OldChicken_ | 来源:发表于2020-01-19 15:36 被阅读0次

    背景

    服务能被优雅停机,指的是:在接收到停机指令后,服务程序应该能拒绝新的请求, 但应该继续完成已经接收请求。

    解决方案

    Graceful Shutdown Spring Boot Applications 这篇文章提供了一个经典的实现优雅停机的实现。

    import org.apache.catalina.connector.Connector;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.event.ContextClosedEvent;
    import java.util.concurrent.Executor;
    import java.util.concurrent.ThreadPoolExecutor;
    import java.util.concurrent.TimeUnit;
    public class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
        private static final Logger log = LoggerFactory.getLogger(GracefulShutdown.class);
        private volatile Connector connector;
        @Override
        public void customize(Connector connector) {
            this.connector = connector;
        }
        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            this.connector.pause();
            Executor executor = this.connector.getProtocolHandler().getExecutor();
            if (executor instanceof ThreadPoolExecutor) {
                try {
                    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
                    threadPoolExecutor.shutdown();
                    if (!threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
                        log.warn("Tomcat thread pool did not shut down gracefully within "
                                + "30 seconds. Proceeding with forceful shutdown");
                    }
                } catch (InterruptedException ex) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
    

    以上代码实现了两个功能:

    1. 实现TomcatConnectorCustomizer,作用是获取tomcat的connector,方便后续对tomcat的连接做操作。
    2. 实现ApplicationListener,监听ApplicationContext发布的事件,该例中监听的是ContextClosedEvent事件,监听到此类事件后把tomcat中connector的线程池shutdown并等待30s,如果所有线程都结束则正常退出,否则发出报警。这里也体现了设计模式中的观察者模式,实现交互对象之间的松耦合。

    设计好listener之后还需要将该listener注册到ApplicationContext中,方便其接受ApplicationContext发布的事件。同时还需将该listener注册到tomcat中,方便获取该Spring应用集成的tomcat的connector。注册的代码如下:

    @Bean
    public GracefulShutdown gracefulShutdown() {
        return new GracefulShutdown();
    }
    @Bean
    public ConfigurableServletWebServerFactory webServerFactory(final GracefulShutdown gracefulShutdown) {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(gracefulShutdown);
        return factory;
    }
    

    相关文章

      网友评论

          本文标题:Spring优雅停止服务的实现及原理分析

          本文链接:https://www.haomeiwen.com/subject/cddrzctx.html