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

藏宝库编辑 2024-9-30 10:40:22 73 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 优雅停机

@SpringBootApplicationpublic 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 优雅停机

@SpringBootApplicationpublic 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            }        }    }}@Componentpublic 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;    }}@Component@AllArgsConstructorpublic 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 优雅停机

默认支持所有哀求完毕后再关闭,缺点:客户端吸取不到相应,有待改进!
干系内容

Shut down embedded servlet container gracefully
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-24 08:18, Processed in 0.148992 second(s), 33 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表