SoFunction
Updated on 2025-04-14

SpringBoot can achieve elegant downtime

The role of elegant downtime in microservice architecture

Imagine you were dining at a restaurant and suddenly the waiter walked over and said, "I'm sorry, I have to get off work, please check out and leave as soon as possible." You may have just ordered the main course, maybe waiting for the dessert, but this sudden notification made you feel very dissatisfied. Your dining experience is interrupted and even your bills can be messy. At the same time, the operation of the restaurant may become unsmooth. After the waiter leaves, the unfinished orders and customer needs may not be processed in time, causing unnecessary trouble.

In a microservice architecture, the corresponding scenario of this situation is the burst closure of the application. Suppose a user is making a request, and while this request is in progress, a microservice is suddenly forced to shut down, or suddenly stopped during maintenance. This will cause the user's operations to be interrupted, unprocessed requests may be lost, and even data inconsistency or errors may occur.

This scenario will not only make the user experience worse, but may also cause great problems to the back-end system. For example, user information may not be saved successfully to the database, or the order status is not updated correctly, resulting in "dirty" or inconsistency in the data. To avoid this problem, elegant downtime mechanisms become crucial in modern microservice systems. It ensures that when the service is closed, all in-progress requests can be processed appropriately, and the relevant resources can be released smoothly, avoiding problems caused by sudden closure of the application.

1. What is elegant shutdown

Simply put, elegantly shut downIt means that when we need to close a service, the service can complete the current work in an orderly manner and stop.Specifically, elegant downtime involves the following steps:

  • Stop receiving new requests: When the system starts to shut down, you need to notify the load balancer or gateway to tell it not to send new requests to the instance that will be offline.
  • Processing ongoing requests: For requests that have arrived and are being processed, the system will give them a chance to complete without sudden interruption.
  • Free up resources: Resources such as database connection pools and thread pools need to be safely released to avoid resource leakage.
  • Persistent temporary data: If necessary, the system saves the current state to the database or file so that it can be restored the next time it starts.

2. Why do you need to be elegantly shut down?

  • Smooth transition when deploying new versions: When we need to update the application, elegant downtime can smoothly shut down the old version of the service, avoiding the impact of sudden downtime on users.
  • Avoid resource leakage: Whether it is memory, database connection, or thread pool resources, they need to be released when closed, otherwise it may lead to memory leaks and other problems.
  • Ensure data consistency: If there are transactions being processed, elegant downtime can give these transactions a chance to complete, avoiding data loss or inconsistency.

3. Practical application scenarios of elegant shutdown

  • Service update: When upgrading the system version, complete request processing and resource release through elegant downtime to avoid interference to users.

  • Flow control: In high concurrency scenarios, if some service nodes need to be temporarily removed, elegant downtime can help achieve "invisible" migration.

  • Order processing: For example, on the taxi platform, the service will be offline after the order is completed to avoid"Abandoned in the middle"The situation.

4. Elegant shutdown may fail

  • Forced close:usekill -9Forced termination of the process will cause the elegant downtime mechanism to fail to trigger.
  • Exhausted resources: Insufficient system resources may cause the cleaning operation to fail.
  • Timeout not configured: If the timeout is not configured, processing long tasks may result in too long downtime.

5. How to achieve elegant shutdown in Spring Boot

Spring Boot's basic implementation of elegant downtime

  • fromSpring Boot 2.3Start with the support of elegant downtime is simpler and more powerful. By settingConfiguration can determine the behavior of the application when the application is down.

Shutdown mode now

  • In Immediate Down mode, the application immediately interrupts all requests and tasks.
server:
  shutdown: immediate

Although simple and efficient, this approach is usually only suitable for testing or stateless services.

Elegant shutdown mode

  • In elegant shutdown mode,Spring BootThe current processing task will be completed before shutting down.
server:
  shutdown: graceful

Note: The default waiting time in this mode is 30 seconds, which can be passed-per-shutdown-phaseMake configuration.

Add spring-boot-starter-actuator dependency

First, make sure your project containsspring-boot-starter-actuatorDependency, this is enabledSpring BootA toolkit for monitoring and managing endpoints built-in.

<dependency>
    <groupId></groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Enable shutdown endpoint

By default,Spring BootofshutdownThe endpoint is disabled. We need toorIt is explicitly enabled in.

for

=true
=shutdown

Or, if you use

management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        include: "shutdown"

Trigger elegant shutdown

After configuration, you can sendHTTPRequest to trigger elegant downtime. For example, usecurlOrder:

curl -X POST http://localhost:8080/actuator/shutdown

When you call this endpoint,Spring BootThe application will stop receiving new requests and continue to process the requests that have been received. The application will not exit until all requests are processed.

6. Implement cleaning logic through the ApplicationListener interface

In order to perform a specific cleanup operation when the application is closed (exampleSuch as closing the database connection and releasing resourcesetc.), you can achieveApplicationListener<ContextClosedEvent>interface.

import ;
import ;
import ;

@Component
public class GracefulShutdownListener implements ApplicationListener&lt;ContextClosedEvent&gt; {
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        // Perform necessary cleaning operations        ("Starting graceful shutdown...");
        try {
            (5000); // Simulate cleaning tasks        } catch (InterruptedException e) {
            ().interrupt();
        }
        ("Graceful shutdown completed.");
    }
}

In this example, we simulated a cleanup operation (by()Come and wait). In fact, you can replace this part of the logic, such as closing the database connection, releasing the file handle, etc.

7. Use JVM hook function

Java provides()Method, you can register a thread to perform a cleanup task when the JVM terminates. This method is suitable for some underlying cleaning operations, especially in some cases,ApplicationListenerThere may not be a chance to be triggered.

import ;
import ;

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {
        // Register to close the hook        ().addShutdownHook(new Thread(() -&gt; {
            ("JVM is shutting down, executing cleanup...");
            try {
                (5000); // Simulate cleaning tasks            } catch (InterruptedException e) {
                ().interrupt();
            }
            ("Cleanup completed.");
        }));

        (, args);
    }
}

It should be noted thatJVMClose the hook is not always possible, especially if it encounters a forced stop (e.g.kill -9)hour. Therefore, it should serve as a supplementary mechanism, not a sole guarantee.

8. How to trigger elegant shutdown

In addition to passing/actuator/shutdownIn addition to endpoints to trigger graceful downtime, there are some common ways:

  • SIGTERM Signal: By sendingSIGTERMSignal (for example, usekillCommand) can triggerJVMnormal exit process.

kill <pid>

Here<pid>It is the application's process ID.

kill -9 pidIt can simulate extreme situations such as system downtime and system power outage, andkill -15 pidIt is waiting for the application to close and perform blocking operations, and sometimes it is impossible to close the application.

#View jvm process pidjps
#List all signal nameskill -l

# Signal constant value under Windows# Abbreviation Full Name Value# INT SIGINT 2 Ctrl+C Interrupt# ILL SIGILL 4 Illegal Directive# FPE SIGFPE 8 floating point exception (floating point exception)# SEGV SIGSEGV 11 segment violation (segment fault)# TERM SIGTERM 5 Software termination signal from kill (the software issued by Kill is terminated)# BREAK SIGBREAK 21 Ctrl-Break sequence(Ctrl+Break interrupt)# ABRT  SIGABRT    22      abnormal termination triggered by abort call(Abort)

#linux signal constant value# Abbreviation Full Name Value# HUP SIGHUP 1 Terminal disconnection# INT SIGINT 2 interrupt (same as Ctrl + C)# QUIT SIGQUIT 3 Exit (same as Ctrl + \)# KILL SIGKILL 9 Forced Termination# TERM SIGTERM 15 Terminate# CONT SIGCONT 18 Continue (as opposed to STOP, fg/bg command)# STOP SIGSTOP 19 Pause (same as Ctrl + Z)#....

#It can be understood that the operating system forces a process from the kernel levelkill -9 pid 
#Understanding it as sending a notification, waiting for the application to actively closekill -15 pid
#It also supports the full name or abbreviation of signal constant values ​​(that is, after removing SIG)kill -l KILL

JVM Tools: Java provides some tools (such asjcmdandjconsole) can be used to control the life cycle of the JVM. For example, usejcmdTo send the exit command:

jcmd <pid> 
  • Container Platform: If your application runs inKubernetesorDockerOn container platforms, the platform will usually send when deleting the container.SIGTERMsignal and wait for the application to complete the work.

Other methods

Implementing Graceful Shutdown in Spring Boot (Graceful Shutdown) in addition to passingspring-boot-actuatorApplicationListener<ContextClosedEvent>andJVM hookIn addition to the methods, there are actually some other ways to help us achieve elegant downtime. The following are several different implementation methods and are in line with practical application scenarios and code examples.

1. Use @PreDestroy annotation

@PreDestroyThe annotation isJava EEOne of the annotations used inBeanPerform a cleanup task before destruction.SpringThis annotation is also supported whenSpringWhen the container is closed, all with@PreDestroyThe annotated methods will be called. It is usually used to perform resource release operations, such as closing database connection pools, cleaning caches, etc.

Code example:

import ;
import ;

@Component
public class GracefulShutdownService {

    @PreDestroy
    public void onShutdown() {
        ("Performing cleanup before shutdown...");
        // Perform resource cleaning here, such as closing database connections, releasing thread pools, etc.    }
}

Applicable scenarios:

  • Suitable for scenarios where resources need to be cleaned when the application is closed, especially in resource management (exampleSuch as closing the connection pool, cleaning the cachewait).
  • existWebIn applications, it is usually used to release connections to external systems (such as databases, message queues, etc.).

2. UseDisposableBeaninterface

Spring providesDisposableBeaninterface, used to defineBeanCleanup operations that need to be performed during destruction. Itsdestroy()The method will beSpringIt is automatically called when the container is closed.

Code example:

Enable Shutdown Hook

Spring BootBy default it will passJVMofShutdown HookTriggers elegant shutdown. Make sure the following configurations are enabled:

spring:
  main:
    register-shutdown-hook: true

Custom resource release logic

If you need to perform specific cleaning operations during downtime, such as closing a database connection or stopping a thread pool, you can addShutdown HookOr realizeDisposableBeanInterface.

import ;
import ;

@Component
public class GracefulShutdownService implements DisposableBean {

    @Override
    public void destroy() throws Exception {
        ("Graceful shutdown - Cleaning up resources...");
        // Perform a cleanup operation    }
}

Or directly implement it through the JVM hook:

().addShutdownHook(new Thread(() -&gt; {
    ("Execute custom resource cleaning logic");
}));

Timeout mechanism

To avoid system downtime blocking due to excessive time-consuming of some requests, you can set the timeout time by:

spring:
  lifecycle:
    timeout-per-shutdown-phase: 20s # Default 30 seconds

Applicable scenarios:

  • and@PreDestroySimilar, butDisposableBeanProvides a clearer way to deal with itSpringIn the containerBeandestroy.
  • Suitable for scenarios where custom cleanup operations are required (such as closing connection pools, stopping background threads, etc.).

3. Use custom thread pool to achieve elegant shutdown

If your application uses a custom thread pool, if you want to ensure that all threads can stop in an orderly manner when the application is closed, you can set the thread poolshutdownorshutdownNowMethod to implement.

Spring Boot provides a variety of ways to create and configure thread pools, such asTaskExecutor@Asyncwait. If the application needs to wait for the task in the thread pool to complete when it is stopped, it can be configured in the following ways.

Code example:

import ;
import ;
import ;
import ;

@Component
public class GracefulShutdownListener implements ApplicationListener&lt;ContextClosedEvent&gt; {

    private final ThreadPoolTaskExecutor taskExecutor;

    public GracefulShutdownListener(ThreadPoolTaskExecutor taskExecutor) {
         = taskExecutor;
    }

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        ("Shutting down thread pool...");
        
        // Give the tasks in the current thread pool some time to complete        ();
        
        try {
            // Wait for the task to be completed            if (!().awaitTermination(60, )) {
                ("Timeout reached, forcing shutdown...");
            }
        } catch (InterruptedException e) {
            ().interrupt();
        }
    }
}

Applicable scenarios:

  • Applicable when your application needs to perform asynchronous tasks and want to ensure that these tasks can be completed in an orderly manner to prevent forced interrupts.
  • Suitable for background thread pools or asynchronous task systems, ensuring that tasks can terminate smoothly when the application is closed.

4. Achieve elegant downtime in Kubernetes

If you willSpring BootApplications are deployed on container orchestration platforms (e.g.Kubernetes)superior,KubernetesIt will automatically help you achieve elegant downtime.KubernetessendSIGTERMand wait for the container to stop for a certain period of time (usually 30 seconds), during which time the application should complete the ongoing request and clean up the resources.

You can set itterminationGracePeriodSecondsTo configure the application on receiptSIGTERMMaximum elegant downtime after signal.

Configuration example (Kubernetes):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: my-app
          image: my-app-image
          ports:
            - containerPort: 8080
      terminationGracePeriodSeconds: 60  # Wait for 60 seconds

Applicable scenarios:

  • When the application is deployed inKubernetesorDocker SwarmWhen like container platforms, this method can automatically trigger elegant shutdowns, in line with the applied elegant shutdown strategies (such as triggering shutdowns through Actuator).
  • Suitable for containerized deployment and cloud-native applications, it can cooperate with the platform's life cycle management mechanism.

5. Use a custom shutdown signal processor

If you don't want to rely entirelySpringThe mechanism provided is to implement a custom signal processor to capture and respond to a shutdown signal. In this way, you can control the downtime process more carefully.

Code example:

import ;

import ;

@Component
public class ShutdownSignalHandler {

    public ShutdownSignalHandler() throws IOException {
        // Register SIGTERM signal processor        ().addShutdownHook(new Thread(this::shutdown));
    }

    private void shutdown() {
        ("Received shutdown signal. Performing graceful shutdown...");
        // Perform cleaning operations, such as closing the connection pool, stopping the background service, etc.    }
}

Applicable scenarios:

  • If you need more flexible and elegant downtime control, you can use a custom signal processor.
  • Suitable for various signals that need to be processed (e.g.SIGTERMSIGINT) complex scenarios, especially for non-Spring infrastructure components.

9. Summary

Elegant shutdown isSpring BootAn important feature of the application, it helps us ensure that resources can be released smoothly when the application is closed, and ongoing requests are processed, thereby improving the stability and reliability of the system. Through Spring Boot Actuator,ApplicationListenerWith multiple methods such as interfaces and JVM hook functions, we can ensure that the application can be closed safely and smoothly without affecting the user experience or causing data loss.

In addition to Spring Boot Actuator andApplicationListenerIn addition, there are many ways to achieve elegant downtime. Each method has different applicable scenarios:

  • @PreDestroyandDisposableBean: Suitable for simple resource release and cleaning operations.
  • Custom thread pool cleaning: Suitable for scenarios where thread pool tasks need to be completed.
  • Elegant downtime of container platforms: Suitable for containerized applications,KubernetesThe elegant downtime of the service will be automatically managed.
  • Custom signal processing: Suitable for downtime processes that require more flexible and underlying control.

Depending on the application's needs, you can choose the right way to achieve elegant downtime, thereby improving system reliability and user experience.

The above is the detailed content of SpringBoot's various ways to achieve elegant shutdown. For more information about SpringBoot's elegant shutdown, please pay attention to my other related articles!