Spring Boot 내장 용기 Tomcat / Undertow / Jetty 우아 한 정지 실현

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 은 정지 신 호 를 받 은 후, 4. 567914. 인터페이스, 4. 567914. 주해 또는 4. 567914. 사건 을 통 해 우아 한 정지 와 관련 된 논 리 를 처리 할 수 있다.
버 전 정보
Spring Boot 버 전: 2.0.0. RELEASE
Tomcat 우아 정지
@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 {
        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 우아 정지
@SpringBootApplication
public class Application {

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

    /**
     *      Spring Boot
     */
    @Component
    public class GracefulShutdown implements ApplicationListener {

        @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 listenerInfo = undertow.getListenerInfo();
                Undertow.ListenerInfo listener = listenerInfo.get(0);
                ConnectorStatistics connectorStatistics = listener.getConnectorStatistics();
                while (connectorStatistics.getActiveConnections() > 0){}
            }catch (Exception e){
                // Application Shutdown
            }
        }
    }
}
@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;
    }

}
@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 우아 정지
모든 요청 이 끝 난 후에 닫 는 것 을 기본 으로 지원 합 니 다. 단점: 클 라 이언 트 가 응답 을 받 지 못 하고 개선 이 필요 합 니 다!
관련 내용
Shut down embedded servlet container gracefully

좋은 웹페이지 즐겨찾기