본문 바로가기
Spring

Spring Boot 기존 요청 스레드 처리하고 안전하게 종료하기

by Gil Granger 2020. 1. 16.

일반적으로 리눅스 환경에서 스프링 부트를 종료시킬때

 

kill -9 [PID]

명령어로 많이 사용하는것을 주위에서 보았다.

 

하지만 이 명령어로 사용하게 되면 처리중인 쓰레드 처리는 강제로 종료하게 되므로 권장하지 않는다.

 

(Spring Boot 2.3 version 부터는 안전하게 종료하도록(graceful shutdown 지원이 된다고 한다.)

 

기존 쓰레드를 처리하고 안전하게 종료할 수 있는 방법 (Embedded Tomcat)

 

public class ShutDownCustom implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
    private static final Logger log = LoggerFactory.getLogger(ShutDownCustom.class);

    private static final int TIMEOUT = 30;

    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(TIMEOUT, TimeUnit.SECONDS)) {
                    log.warn("Tomcat thread pool did not shut down gracefully within "
                            + TIMEOUT + " seconds. Proceeding with forceful shutdown");

                    threadPoolExecutor.shutdownNow();

                    if (!threadPoolExecutor.awaitTermination(TIMEOUT, TimeUnit.SECONDS)) {
                        log.error("Tomcat thread pool did not terminate");
                    }
                }
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    }
}

참고(https://blog.marcosbarbero.com/graceful-shutdown-spring-boot-apps/)

 

 

그 다음 빈을 등록해주면 된다.

  @Bean
  public ShutDownCustom shutdown() {
    return new ShutDownCustom();
  }
  @Bean
  public ConfigurableServletWebServerFactory webServerFactory(final ShutDownCustom shutDownCustom) {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.addConnectorCustomizers(shutDownCustom);
    return factory;
  }

 

 

테스트 방법은 간단하다.

 

블로그에서 제시하는 것처럼 테스트할 요청에 딜레이를 주고 처리되는 시간 안에 종료를 시키는 것이다.

 

  @GetMapping("/delay")
  public String delay() throws InterruptedException {
    Thread.sleep(10000);
    return "success";
  }

 

종료는 

 

kill -15 [PID]  


kill [PID]

 

이 두가지중에 하나의 명령어로 종료한다.

 

 

 

이렇게 테스트 해보면 종료를 하더라도 정상적으로 딜레이 이후에 success 메세지가 출력이 되는것을 확인 할 수 있다.

 

 

댓글