Mechanizm Graceful Shutdown w Spring Boot
Mechanizm Graceful Shutdown w Spring Boot
Bezpieczne zamknięcie aplikacji Graceful Shutdown to mechanizm który pozwala zamknąć aplikację wyłączając uprzednie wszystkie inne procesy w pewnym ustalonym czasie. Jeśli czas ten zostanie przekroczony to jest to sytuacja wyjątkowa którą należy prawidłowo obsłużyć. Zaczynamy! Tworzymy nowy projekt Spring Boota a następnie:
Pierwszy komponent – założony czas na zamknięcie procesów to 20 sekund:
@Component public class GracefulShutdown implements ApplicationListener<ContextClosedEvent> { private final TomcatGracefulShutdownConnector gracefulShutdown; public GracefulShutdown(final TomcatGracefulShutdownConnector gracefulShutdown) { this.gracefulShutdown = gracefulShutdown; } @Override public void onApplicationEvent(final ContextClosedEvent contextClosedEvent) { try { final ThreadPoolExecutor threadPoolExecutor = gracefulShutdown.threadPoolExecutor().orElseThrow(() -> new IllegalStateException()); threadPoolExecutor.shutdown(); if(!threadPoolExecutor.awaitTermination(20, TimeUnit.SECONDS)) { System.out.println("time out..."); } else { System.out.println("graceful activated"); } } catch(InterruptedException ex) { Thread.currentThread().interrupt(); } } }
Drugi komponent:
public class TomcatGracefulShutdownConnector implements TomcatConnectorCustomizer { private volatile Connector connector; @Override public void customize(final Connector connector) { this.connector = connector; } public Optional<ThreadPoolExecutor> threadPoolExecutor() { this.connector.pause(); Executor executor = this.connector.getProtocolHandler().getExecutor(); if(executor instanceof ThreadPoolExecutor) { return Optional.of((ThreadPoolExecutor) executor); } return Optional.empty(); } }
RestController:
@RestController public class RestControllerProcess { @GetMapping("/process-1") String longJob() throws InterruptedException { Thread.sleep(15_000); return "Done"; } @GetMapping("/process-2") String veryLongJob() throws InterruptedException { Thread.sleep(25_000); return "Done"; } }
Klasa startowa:
@SpringBootApplication public class GracefulShutdownApplication { public static void main(String[] args) { SpringApplication.run(GracefulShutdownApplication.class, args); } @Bean public TomcatGracefulShutdownConnector tomcatGracefulShutdownConnector() { return new TomcatGracefulShutdownConnector(); } @Bean public ConfigurableServletWebServerFactory webServerFactory(final TomcatGracefulShutdownConnector tomcatGracefulShutdownConnector) { TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(); factory.addConnectorCustomizers(tomcatGracefulShutdownConnector); return factory; } }
Testy:
Uruchamiamy:
http://localhost:8080/process-1
i z poziomu IntelliJ wysyłamy sygnał sigterm:
Wynik:
graceful activated
Uruchamiany:
http://localhost:8080/process-2
i z poziomu IntelliJ wysyłamy sygnał sigterm:
Wynik:
time out...
Leave a comment