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:use
kill -9
Forced 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
- from
Spring Boot 2.3
Start 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 Boot
The 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-phase
Make configuration.
Add spring-boot-starter-actuator dependency
First, make sure your project containsspring-boot-starter-actuator
Dependency, this is enabledSpring Boot
A toolkit for monitoring and managing endpoints built-in.
<dependency> <groupId></groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Enable shutdown endpoint
By default,Spring Boot
ofshutdown
The endpoint is disabled. We need toor
It 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 sendHTTP
Request to trigger elegant downtime. For example, usecurl
Order:
curl -X POST http://localhost:8080/actuator/shutdown
When you call this endpoint,Spring Boot
The 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<ContextClosedEvent> { @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,ApplicationListener
There 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(() -> { ("JVM is shutting down, executing cleanup..."); try { (5000); // Simulate cleaning tasks } catch (InterruptedException e) { ().interrupt(); } ("Cleanup completed."); })); (, args); } }
It should be noted thatJVM
Close 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/shutdown
In addition to endpoints to trigger graceful downtime, there are some common ways:
SIGTERM Signal: By sending
SIGTERM
Signal (for example, usekill
Command) can triggerJVM
normal exit process.
kill <pid>
Here<pid>
It is the application's process ID.
kill -9 pid
It can simulate extreme situations such as system downtime and system power outage, andkill -15 pid
It 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 asjcmd
andjconsole
) can be used to control the life cycle of the JVM. For example, usejcmd
To send the exit command:
jcmd <pid>
Container Platform: If your application runs in
Kubernetes
orDocker
On container platforms, the platform will usually send when deleting the container.SIGTERM
signal and wait for the application to complete the work.
Other methods
Implementing Graceful Shutdown in Spring Boot (Graceful Shutdown) in addition to passingspring-boot-actuator
、ApplicationListener<ContextClosedEvent>
andJVM hook
In 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
@PreDestroy
The annotation isJava EE
One of the annotations used inBean
Perform a cleanup task before destruction.Spring
This annotation is also supported whenSpring
When the container is closed, all with@PreDestroy
The 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).
- exist
Web
In applications, it is usually used to release connections to external systems (such as databases, message queues, etc.).
2. UseDisposableBean
interface
Spring providesDisposableBean
interface, used to defineBean
Cleanup operations that need to be performed during destruction. Itsdestroy()
The method will beSpring
It is automatically called when the container is closed.
Code example:
Enable Shutdown Hook
Spring Boot
By default it will passJVM
ofShutdown 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 realizeDisposableBean
Interface.
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(() -> { ("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
@PreDestroy
Similar, butDisposableBean
Provides a clearer way to deal with itSpring
In the containerBean
destroy. - 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 poolshutdown
orshutdownNow
Method to implement.
Spring Boot provides a variety of ways to create and configure thread pools, such asTaskExecutor
、@Async
wait. 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<ContextClosedEvent> { 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 Boot
Applications are deployed on container orchestration platforms (e.g.Kubernetes
)superior,Kubernetes
It will automatically help you achieve elegant downtime.Kubernetes
sendSIGTERM
and 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 itterminationGracePeriodSeconds
To configure the application on receiptSIGTERM
Maximum 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 in
Kubernetes
orDocker Swarm
When 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 entirelySpring
The 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.
SIGTERM
、SIGINT
) complex scenarios, especially for non-Spring infrastructure components.
9. Summary
Elegant shutdown isSpring Boot
An 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,ApplicationListener
With 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 andApplicationListener
In addition, there are many ways to achieve elegant downtime. Each method has different applicable scenarios:
-
@PreDestroy
andDisposableBean
: 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,
Kubernetes
The 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!