Fahren Sie eine Spring Boot-Anwendung herunter

1. Übersicht

Das Verwalten des Lebenszyklus von Spring Boot Application ist für ein produktionsfähiges System sehr wichtig. Der Spring-Container übernimmt die Erstellung, Initialisierung und Zerstörung aller Beans mithilfe des ApplicationContext.

Der Schwerpunkt dieses Aufsatzes liegt auf der Zerstörungsphase des Lebenszyklus. Insbesondere werden wir uns verschiedene Möglichkeiten ansehen, wie eine Spring Boot-Anwendung heruntergefahren werden kann.

Weitere Informationen zum Einrichten eines Projekts mit Spring Boot finden Sie im Artikel Spring Boot Starter oder in der Spring Boot-Konfiguration.

2. Endpunkt herunterfahren

Standardmäßig sind alle Endpunkte in Spring Boot Application außer / shutdown aktiviert . Dies ist natürlich Teil der Actuator- Endpunkte.

Hier ist die Maven-Abhängigkeit, um diese einzurichten:

 org.springframework.boot spring-boot-starter-actuator 

Und wenn wir auch Sicherheitsunterstützung einrichten möchten, benötigen wir:

 org.springframework.boot spring-boot-starter-security 

Zuletzt aktivieren wir den Endpunkt zum Herunterfahren in der Datei application.properties :

management.endpoints.web.exposure.include=* management.endpoint.shutdown.enabled=true endpoints.shutdown.enabled=true

Beachten Sie, dass wir auch alle Aktuatorendpunkte verfügbar machen müssen, die wir verwenden möchten. Im obigen Beispiel haben wir alle Aktuatorendpunkte verfügbar gemacht, die den Endpunkt / shutdown enthalten .

Um die Spring Boot-Anwendung herunterzufahren, rufen Sie einfach eine POST-Methode wie folgt auf :

curl -X POST localhost:port/actuator/shutdown

In diesem Aufruf wird die Port stellt den Aktor - Anschluss.

3. Schließen Sie den Anwendungskontext

Wir können die Methode close () auch direkt über den Anwendungskontext aufrufen .

Beginnen wir mit einem Beispiel zum Erstellen und Schließen eines Kontexts:

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class).web(WebApplicationType.NONE).run(); System.out.println("Spring Boot application started"); ctx.getBean(TerminateBean.class); ctx.close();

Dadurch werden alle Bohnen zerstört, die Sperren aufgehoben und die Bohnenfabrik geschlossen . Um das Herunterfahren der Anwendung zu überprüfen, verwenden wir den Standard-Lebenszyklus-Rückruf von Spring mit der Annotation @PreDestroy :

public class TerminateBean { @PreDestroy public void onDestroy() throws Exception { System.out.println("Spring Container is destroyed!"); } }

Wir müssen auch eine Bohne dieses Typs hinzufügen:

@Configuration public class ShutdownConfig { @Bean public TerminateBean getTerminateBean() { return new TerminateBean(); } }

Hier ist die Ausgabe nach dem Ausführen dieses Beispiels:

Spring Boot application started Closing [email protected] DefaultLifecycleProcessor - Stopping beans in phase 0 Unregistering JMX-exposed beans on shutdown Spring Container is destroyed!

Das Wichtigste dabei ist: Beim Schließen des Anwendungskontexts wird der übergeordnete Kontext aufgrund separater Lebenszyklen nicht beeinflusst .

3.1. Schließen Sie den aktuellen Anwendungskontext

Im obigen Beispiel haben wir einen untergeordneten Anwendungskontext erstellt und ihn dann mit der Methode close () zerstört.

Wenn wir den aktuellen Kontext schließen möchten, besteht eine Lösung darin, einfach den Endpunkt Aktuator / Herunterfahren aufzurufen .

Wir können jedoch auch unseren eigenen benutzerdefinierten Endpunkt erstellen:

@RestController public class ShutdownController implements ApplicationContextAware { private ApplicationContext context; @PostMapping("/shutdownContext") public void shutdownContext() { ((ConfigurableApplicationContext) context).close(); } @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.context = ctx; } }

Hier haben wir einen Controller hinzugefügt, der die ApplicationContextAware- Schnittstelle implementiert und die Setter-Methode überschreibt, um den aktuellen Anwendungskontext abzurufen. Dann rufen wir in einer Mapping-Methode einfach die close () -Methode auf.

Wir können dann unseren neuen Endpunkt aufrufen, um den aktuellen Kontext herunterzufahren:

curl -X POST localhost:port/shutdownContext

Wenn Sie einen Endpunkt wie diesen in einer realen Anwendung hinzufügen, möchten Sie ihn natürlich auch sichern.

4. Beenden Sie SpringApplication

SpringApplication registriert einen Shutdown- Hook bei der JVM, um sicherzustellen, dass die Anwendung ordnungsgemäß beendet wird.

Beans können die ExitCodeGenerator- Schnittstelle implementieren , um einen bestimmten Fehlercode zurückzugeben:

ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class) .web(WebApplicationType.NONE).run(); int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() { @Override public int getExitCode() { // return the error code return 0; } }); System.exit(exitCode);

Der gleiche Code mit der Anwendung von Java 8 Lambdas:

SpringApplication.exit(ctx, () -> 0);

Nach dem Aufruf von System.exit (exitCode) wird das Programm mit einem 0-Rückkehrcode beendet :

Process finished with exit code 0

5. Beenden Sie den App-Prozess

Schließlich können wir eine Spring Boot-Anwendung auch von außerhalb der Anwendung mithilfe eines Bash-Skripts herunterfahren. Unser erster Schritt für diese Option besteht darin, dass der Anwendungskontext seine PID in eine Datei schreibt:

SpringApplicationBuilder app = new SpringApplicationBuilder(Application.class) .web(WebApplicationType.NONE); app.build().addListeners(new ApplicationPidFileWriter("./bin/shutdown.pid")); app.run();

Erstellen Sie als Nächstes eine shutdown.bat- Datei mit folgendem Inhalt:

kill $(cat ./bin/shutdown.pid)

Die Ausführung von shutdown.bat extrahiert die Prozess-ID aus der Datei shutdown.pid und beendet die Boot-Anwendung mit dem Befehl kill .

6. Fazit

In this quick write-up, we've covered few simple methods that can be used to shut down a running Spring Boot Application.

While it's up to the developer to choose an appropriate a method; all of these methods should be used by design and on purpose.

For example, .exit() is preferred when we need to pass an error code to another environment, say JVM for further actions. UsingApplicationPID gives more flexibility, as we can also start or restart the application with the use of bash script.

Finally, /shutdownis here to make it possible to terminate the applications externally via HTTP. For all the other cases .close() will work perfectly.

Wie üblich ist der vollständige Code für diesen Artikel im GitHub-Projekt verfügbar.