sourcecode

스프링 부트 셧다운 훅

codebag 2023. 3. 19. 18:09
반응형

스프링 부트 셧다운 훅

Spring Boot 어플리케이션이 셧다운되었을 때 발생하는 커스텀셧다운 루틴을 등록/추가하려면 어떻게 해야 합니까?

시나리오:Spring Boot 어플리케이션을 Jetty 서블릿컨테이너(내장 Jetty 없음)에 전개합니다.응용 프로그램에서 로그백을 로그백에 사용하고 있으며 실행 시 로그백의 MBean JMX 컨피규레이터를 사용하여 로그 레벨을 변경하려고 합니다. 문서에는 메모리 누수를 피하기 위해 셧다운특정 Logger Context 셧다운 방식을 호출해야 한다고 기재되어 있습니다.

Spring Boot 셧다운 이벤트를 청취하는 좋은 방법은 무엇입니까?

시도했습니다.

public static void main(String[] args) throws Exception {
    ConfigurableApplicationContext cac = SpringApplication.run(Example.class, args);

    cac.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            logger.info("Do something");
        }
    });
}

단, 어플리케이션이 셧다운되어도 이 등록된 리스너는 호출되지 않습니다.

https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/ #spring.spring-application.application-filename

각 Spring Application은 종료 시 ApplicationContext가 정상적으로 닫히도록 하기 위해 JVM에 셧다운 후크를 등록합니다.모든 표준 Spring 라이프 사이클 콜백(DisposableBean 인터페이스 또는 @PreDestroy 주석 등)을 사용할 수 있습니다.

또한 콩은 org.springframework.boot를 구현할 수 있습니다.응용 프로그램 종료 시 특정 종료 코드를 반환하는 경우 ExitCodeGenerator 인터페이스.

@syclick이 말한 대로 이것을 시도해 본 적이 있습니까?

@SpringBootApplication
@Slf4j
public class SpringBootShutdownHookApplication {

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

  @PreDestroy
  public void onExit() {
    log.info("###STOPing###");
    try {
      Thread.sleep(5 * 1000);
    } catch (InterruptedException e) {
      log.error("", e);;
    }
    log.info("###STOP FROM THE LIFECYCLE###");
  }
}

리스너가 너무 늦게 등록되었습니다(콘텍스트가 이미 닫힐 때까지 이 회선은 도달하지 않습니다).이 정도면 충분할 거야@Bean.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

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

    @NotNull
    @Bean
    ServletListenerRegistrationBean<ServletContextListener> myServletListener() {
        ServletListenerRegistrationBean<ServletContextListener> srb =
                new ServletListenerRegistrationBean<>();
        srb.setListener(new ExampleServletContextListener());
        return srb;
    }
}

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class ExampleServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(
        ServletContextEvent sce) {
    // Context Initialised
    }

    @Override
    public void contextDestroyed(
        ServletContextEvent sce) {
       // Here - what you want to do that context shutdown    
   }
}

서버의 셧다운 프로세스를 몇 분간 보류해야 하는 유사한 사용 사례가 있습니다.질문에 기재된 것과 같은 접근방식을 사용하고 있습니다.다만 변경된 것은 서비스를 부팅한 후에 리스너를 추가하는 대신 리스너를 추가하는 것입니다.(ContextClosedEvent응용 프로그램을 실행하기 전에)

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.addListeners((ApplicationListener<ContextClosedEvent>) event -> {
            log.info("Shutdown process initiated...");
            try {
                Thread.sleep(TimeUnit.MINUTES.toMillis(5));
            } catch (InterruptedException e) {
                log.error("Exception is thrown during the ContextClosedEvent", e);
            }
            log.info("Graceful Shutdown is processed successfully");
        });
        application.run(args);
    }
}

언급URL : https://stackoverflow.com/questions/26678208/spring-boot-shutdown-hook

반응형