Using the Spring Boot actuator to shutdown a rest

2019-05-05 09:30发布

问题:

This is a followup question to How to shutdown a Spring Boot Application in a correct way?

Suppose we have a server that has 3 clients currently connected and each client is running a long job. We then shutdown the server with the command:

curl -X POST localhost:port/shutdown

Does that:

A) Let the server finish the jobs that the 3 clients are running before shutting down?

B) Disallow any other connections from happening such that the server will eventually shut down?

回答1:

The Spring Boot shutdown endpoint invokes this class: org.springframework.boot.actuate.endpoint.ShutdownEndpoint which invokes close() on your ApplicationContext. This in turn ...

  • destroys beans
  • closes the bean factory
  • stops the embedded servlet container

If your beans are ordered and have carefully written shutdown methods, then this should be fine. But if not, then at some point in that shutdown cycle "the jobs that the 3 clients are running" are likely to be interrupted. In addition, it is possible that new connections may be made in the small time window between you invoking shutdown and the shutdown cycle kicking in.

Spring provides application events and listener hooks which allow you to participate in the shutdown cycle. The ContextClosedEvent is published before beans are destroyed, the embedded container is shutdown, etc, so you can use this to implement your own shutdown behaviour before the default behaviour kicks in. For example:

public class ShutdownListener implements ApplicationListener<ContextClosedEvent> {
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        // 
    }
}

You could implement this listener such that it

  • Rejects connection requests with a HTTP 503 (or something equivalent to that if you are not dealing with HTTP requests)
  • Pauses to allow any inflight jobs to complete before continuing with the shutdown cycle

You register this listener in the same way as you register any ApplicationListener in Spring Boot e.g.

SpringApplication app = new SpringApplication(MyApplication.class);
app.addListeners(new ShutdownListener());