For microservices, graceful offline service is a necessity.

For online, services should not be exposed if the component or container is not successfully started, and for offline, services should be taken offline if the machine is down, so as to prevent upstream traffic from entering the unhealthy machine.

Elegant offline

Base offline (Spring/SpringBoot/ built-in container)

First, the JVM itself supports graceful shutdownHook.

This mode supports graceful downtime in the following scenarios:

  1. Program exit normally
  2. Using the System. The exit ()
  3. Use Ctrl+C for terminal
  4. Use the Kill PID command to Kill a process

So if you just want to kill -9 the program is going to be overwhelmed.

In Springboot, shutdownHook is already implemented for you, which can respond to Ctrl+ C or kill -15 TERM signals.

Just started an application, and then Ctrl + c, observe the log, it in AnnotationConfigEmbeddedWebApplicationContext this class to print out the suspected Closing… Log, the real implementation logic in his father’s class AbstractApplicationContext (this is in the spring class, what does it mean, in the spring will support the extension of elegant downtime).

What can we do with it? Well, obviously, in the doClose method it publishes a ContextClosedEvent for our extension.

So we can write a listener to listen for ContextClosedEvent and do logoff logic when an event occurs, which in the case of microservices is to unregister the service from the registry.

One question might be, in microservices, logout is usually the first step to gracefully log off, followed by the shutdown operation, so what happens when the traffic comes in?

I would suggest that after logging out of the service, the request baffle can be turned on to reject the traffic, and the rejected traffic can be processed through the failover function of the microservice framework itself. In addition, pay attention to the public number of Java technology stack, in the background reply: interview, you can get my organized Java, Spring Boot series of interview questions and answers, very complete.

Logoff in Docker

I use Docker to deploy the service, whether to support elegant offline.

Here’s what docker’s stop commands do:

Generally speaking, normal people may use docker stop or Docker kill commands to close containers (of course, if USR2 custom information was registered in the previous step, it may be closed by docker exec kill -12).

For docker Stop, it sends a SIGTERM(kill -15 term message) to the container’s PID1 process, and by default, it waits 10 seconds before sending a SIGKILL(kill -9 message) to PID1.

Obviously, Docker Stop allows an application to have a default reaction time of 10 seconds to perform a graceful shutdown, as long as the application responds to a kill -15 signal, as described in the previous step. So that’s a good way to do it.

Of course, if the shutdownHook method executes for more than 50 years, it’s definitely not elegant. You can add the wait time with docker stop -t.

Shutdown script for external containers (Jetty)

If you have to deploy in an external container (I think it is a waste of resources and increases complexity). So can we gracefully shut down.

Yes and yes, there are two ways:

First, the RPC framework itself provides elegant up-down interfaces that can be called to end the entire application lifecycle, and extension points that allow developers to customize the downtime logic for services to go offline. At the same time, the call to this interface is encapsulated as a preStop operation and solidified in the Shutdown script of Jetty and other containers, ensuring that the offline interface is called before the container is stopped to end the application life cycle. In the shutdown script, the execution class initiates the offline service -> closes the port -> checks the offline service until it is complete -> closes the container.

An easier alternative is to simply add the kill -15 command to the script.

Elegant online

Gracefully launching may be more difficult because there is no default implementation, but in general, a rule of thumb is to ensure that the port exists before launching the service.

Springboot built-in container comes online gracefully

This is very simple, and the industry in the application layer of elegant on-line are implemented under the premise of the built-in container, and can also be used with a series of health checks. Spring Boot gracefully turns off new poses, check this out.

See sofA-Boot health check source code, it will start the program on springboot components to do some health check, and then on some of its own sofa middleware health check, the whole health check process after (Sofaboot is currently unable to do their own application level health check, It has a write interface, but the port is ready… Will expose the service or gracefully online, then its health check when it:

You can see that it’s listening for the ContextRefreshedEvent event. In the built-in container mode, the start method of the built-in container mode is in the refreshContext method, and a ContextRefreshedEvent event is issued after the method is executed. That is to say, the built-in container must be started successfully when the event is heard.

However, the event of ContextRefreshedEvent will be monitored for many times in some specific scenes due to various reasons, so there is no way to ensure that the current event is the last one, so as to correctly execute the elegant online logic.

An even more recent event in SpringBoot is called ApplicationReadyEvent, which is published on the listeners. Finished (context, null) after afterRefresh. It is absolutely guaranteed that the built-in container port exists, so we can listen for this event to do elegant on-line logic and even integrate middleware related health checks here.

The external container (Jetty) comes online gracefully

The deployment mode of most current applications, whether jetty or Docker (also using Jetty images), is essentially an external container. This situation is more difficult, at least at the application level, because the external container is not visible, and the container itself provides no hooks for you to implement.

Then, as with graceful going-on, RPC frameworks need to provide graceful going-on interfaces to initiate the entire application lifecycle and extension points for developers to perform custom going-on logic (reporting version detection information, etc.). This interface is also called as a postStart operation, which is solidified in the Startup script of external containers such as Jetty to ensure that the application is online after the container is started. The container performs a process similar to starting the container -> Health Check -> Online service logic -> Health online service until complete.