Graceful Shutdown in Spring Boot 2.3 and Earlier Versions
This article explains how to enable and use Spring Boot's graceful shutdown feature in version 2.3, including configuration of the embedded web server and Actuator, and also provides a custom solution for older Spring Boot releases to achieve smooth termination of ongoing requests.
Graceful shutdown means that after sending a stop command to an application process, ongoing business operations are allowed to finish while the application stops accepting new requests.
Spring Boot 2.3 introduced built‑in graceful shutdown support for its four embedded web servers (Jetty, Reactor Netty, Tomcat, Undertow) and both reactive and servlet‑based applications.
Spring Boot 2.3 Graceful Shutdown
Create a Spring Boot web project using version 2.3.0.RELEASE; the embedded Tomcat version is 9.0.35.
Add the following configuration to application.yml to enable graceful shutdown:
# Enable graceful shutdown (default is IMMEDIATE)
server:
shutdown: graceful
# Maximum wait time
spring:
lifecycle:
timeout-per-shutdown-phase: 30sThe core logic resides in
org.springframework.boot.web.embedded.tomcat.GracefulShutdown, which first stops accepting new external requests and then processes the ones already received.
To shut down the Spring context gracefully, add the Actuator dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>Expose the shutdown endpoint via configuration:
# Expose shutdown endpoint
management:
endpoint:
shutdown:
enabled: true
endpoints:
web:
exposure:
include: shutdownThe shutdown logic is implemented in org.springframework.boot.actuate.context.ShutdownEndpoint, which calls doClose() on the applicationContext.
Create a controller WorkController with a long‑running work() method to simulate a heavy business process:
@RestController
public class WorkController {
@GetMapping("/work")
public String work() throws InterruptedException {
// Simulate complex business processing
Thread.sleep(10 * 1000L);
return "success";
}
}Start the application and invoke http://localhost:8080/work to begin processing, then call http://localhost:8080/actuator/shutdown. The shutdown response is:
{
"message": "Shutting down, bye..."
}New requests to /work are rejected while the in‑flight request completes, as shown by the service logs:
2020-05-20 23:05:15.163 INFO 102724 --- [ Thread-253] o.s.b.w.e.tomcat.GracefulShutdown : Commencing graceful shutdown. Waiting for active requests to complete
2020-05-20 23:05:15.287 INFO 102724 --- [tomcat-shutdown] o.s.b.w.e.tomcat.GracefulShutdown : Graceful shutdown complete
2020-05-20 23:05:15.295 INFO 102724 --- [ Thread-253] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'For older Spring Boot versions (e.g., 2.2.6.RELEASE) that lack built‑in graceful shutdown, a custom solution can be implemented by creating a TomcatConnectorCustomizer and an ApplicationListener<ContextClosedEvent> to pause the connector and shut down the thread pool gracefully:
@FunctionalInterface
public interface TomcatConnectorCustomizer {
void customize(Connector connector);
}
@Bean
public GracefulShutdown gracefulShutdown() {
return new GracefulShutdown();
}
private static class GracefulShutdown implements TomcatConnectorCustomizer, ApplicationListener<ContextClosedEvent> {
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) {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
threadPoolExecutor.shutdown();
try {
if (!threadPoolExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
log.warn("Tomcat thread pool did not shut down gracefully within 30 seconds. Proceeding with forceful shutdown");
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
}Register the customizer with the embedded Tomcat factory:
@Bean
public ConfigurableServletWebServerFactory tomcatCustomizer() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addConnectorCustomizers(gracefulShutdown());
return factory;
}Both approaches ensure that ongoing requests finish before the application stops, preventing abrupt termination and potential business errors.
Summary
The article demonstrates how to configure graceful shutdown in Spring Boot 2.3 and earlier versions, using built‑in features and custom code, and highlights security considerations when exposing the Actuator shutdown endpoint.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
