Im Spring Boot-Dokument heißt es: "Jede SpringApplication registriert einen Shutdown-Hook bei der JVM, um sicherzustellen, dass der ApplicationContext beim Beenden ordnungsgemäß geschlossen wird."
Wenn ich ctrl+c
auf den Shell-Befehl klicke, kann die Anwendung ordnungsgemäß heruntergefahren werden. Wenn ich die Anwendung auf einer Produktionsmaschine ausführe, muss ich den Befehl verwenden
java -jar ProApplicaton.jar
. Aber ich kann das Shell-Terminal nicht schließen, sonst wird der Prozess geschlossen.
Wenn ich einen Befehl wie ausführe nohup java -jar ProApplicaton.jar &
, kann ich ihn nicht ordnungsgemäß ctrl+c
herunterfahren.
Was ist der richtige Weg, um eine Spring Boot-Anwendung in der Produktionsumgebung zu starten und zu stoppen?
linux
spring
spring-boot
Chris
quelle
quelle
kill -SIGTERM <PID>
sollte den Trick machen.Antworten:
Wenn Sie das Aktuatormodul verwenden, können Sie die Anwendung über
JMX
oderHTTP
wenn der Endpunkt aktiviert ist, herunterfahren .hinzufügen zu
application.properties
:Folgende URL wird verfügbar sein:
/actuator/shutdown
- Ermöglicht das ordnungsgemäße Herunterfahren der Anwendung (standardmäßig nicht aktiviert).Abhängig davon, wie ein Endpunkt verfügbar gemacht wird, kann der vertrauliche Parameter als Sicherheitshinweis verwendet werden.
Beispielsweise benötigen vertrauliche Endpunkte einen Benutzernamen / ein Kennwort, wenn auf sie zugegriffen wird
HTTP
(oder werden einfach deaktiviert, wenn die Websicherheit nicht aktiviert ist).Aus der Spring-Boot-Dokumentation
quelle
Hier ist eine weitere Option, bei der Sie den Code nicht ändern oder einen heruntergefahrenen Endpunkt verfügbar machen müssen. Erstellen Sie die folgenden Skripte und verwenden Sie sie, um Ihre App zu starten und zu stoppen.
start.sh
Startet Ihre App und speichert die Prozess-ID in einer Datei
stop.sh
Stoppt Ihre App mit der gespeicherten Prozess-ID
start_silent.sh
Wenn Sie die App mit ssh von einem Remotecomputer oder einer CI-Pipeline aus starten müssen, verwenden Sie stattdessen dieses Skript, um Ihre App zu starten. Wenn Sie start.sh direkt verwenden, kann die Shell hängen bleiben.
Nach z. Wenn Sie Ihre App erneut bereitstellen, können Sie sie neu starten, indem Sie:
quelle
nohup
, können Sie einfach die Befehle zusammenführenZur Antwort von @ Jean-Philippe Bond:
Hier ist ein kurzes Maven-Beispiel für Maven-Benutzer zum Konfigurieren des HTTP-Endpunkts zum Herunterfahren einer Spring-Boot-Web-App mithilfe des Spring-Boot-Starter-Aktuators, damit Sie Folgendes kopieren und einfügen können:
1.Maven pom.xml:
2.application.properties:
Alle Endpunkte sind hier aufgelistet :
3.Senden Sie eine Post-Methode, um die App herunterzufahren:
Sicherheitshinweis:
Wenn Sie die Shutdown-Methode auth protected benötigen, benötigen Sie möglicherweise auch
Details konfigurieren :
quelle
server.contextPath=/appName
in meine application.properties aufgenommen habe, würde der Befehl zum Herunterfahren jetzt lauten: Ichcurl -X POST localhost:8080/appName/shutdown
hoffe, es kann jemandem helfen. Ich musste wegen dieses Fehlers viel kämpfen.endpoints.shutdown.enabled=true management.security.enabled=false
.Sie können die Springboot-Anwendung veranlassen, die PID in eine Datei zu schreiben, und Sie können die PID-Datei verwenden, um zu stoppen oder neu zu starten oder den Status mithilfe eines Bash-Skripts abzurufen. Um die PID in eine Datei zu schreiben, registrieren Sie einen Listener für SpringApplication mit ApplicationPidFileWriter wie folgt:
Schreiben Sie dann ein Bash-Skript, um die Spring-Boot-Anwendung auszuführen. Referenz .
Jetzt können Sie das Skript zum Starten, Stoppen oder Neustarten verwenden.
quelle
Allen Antworten scheint die Tatsache zu fehlen, dass Sie möglicherweise einen Teil der Arbeit während des ordnungsgemäßen Herunterfahrens (z. B. in einer Unternehmensanwendung) koordiniert ausführen müssen.
@PreDestroy
Mit dieser Option können Sie den Shutdown-Code in den einzelnen Beans ausführen. Etwas Anspruchsvolleres würde so aussehen:quelle
Ich mache keine Endpunkte verfügbar und beginne ( mit nohup im Hintergrund und ohne durch nohup erstellte Out-Dateien ) und stoppe mit dem Shell-Skript (mit KILL PID anmutig und erzwinge das Töten, wenn die App nach 3 Minuten noch läuft ). Ich erstelle einfach eine ausführbare JAR-Datei und verwende den PID-Dateischreiber, um eine PID-Datei zu schreiben und Jar und Pid in einem Ordner mit demselben Namen wie der Anwendungsname zu speichern. Shell-Skripte haben auch denselben Namen mit Start und Stopp am Ende. Ich rufe diese Stoppskripte auf und starte die Skripte auch über die Jenkins-Pipeline. Bisher keine Probleme. Perfekt für 8 Anwendungen geeignet (Sehr allgemeine Skripte und einfach für jede App anzuwenden).
Hauptklasse
YML-DATEI
Hier ist das Startskript (start-appname.sh):
Hier ist das Stoppskript (stop-appname.sh):
quelle
Spring Boot stellte mehrere Anwendungslistener bereit, während versucht wurde, einen Anwendungskontext zu erstellen. Einer davon ist ApplicationFailedEvent. Wir können verwenden, um zu wissen, ob der Anwendungskontext initialisiert wurde oder nicht.
Zur obigen Listener-Klasse zu SpringApplication hinzufügen.
quelle
SpringApplication registriert implizit einen Shutdown-Hook bei der JVM, um sicherzustellen, dass ApplicationContext beim Beenden ordnungsgemäß geschlossen wird. Dadurch werden auch alle mit annotierten Bean-Methoden aufgerufen
@PreDestroy
. Das heißt, wir müssen dieregisterShutdownHook()
Methode aConfigurableApplicationContext
in einer Boot-Anwendung nicht explizit verwenden , wie wir es in einer Spring Core-Anwendung tun müssen.quelle
@PostConstruct
und habe@PreDestroy
ich die AttributeinitMethod
unddestroyMethod
in der@Bean
Anmerkung verwendet. Also für dieses Beispiel :@Bean(initMethod="init", destroyMethod="destroy")
.@PreDestroy
wenige Entwickler möglicherweise nicht kennen, ist, dass solche Methoden nur für Beans mit Singleton-Gültigkeitsbereich aufgerufen werden. Die Entwickler müssen den Bereinigungsteil des Bean-Lebenszyklus für andere Bereiche verwaltenAb Spring Boot 2.3 und höher ist ein ordnungsgemäßer Mechanismus zum ordnungsgemäßen Herunterfahren integriert .
Pre-Spring Boot 2.3 gibt es keinen sofort einsatzbereiten Mechanismus zum ordnungsgemäßen Herunterfahren. Einige Spring-Boot-Starter bieten diese Funktionalität:
Ich bin der Autor von nr. 1. Der Starter heißt "Hiatus for Spring Boot". Es funktioniert auf der Ebene des Lastenausgleichs, dh es markiert den Dienst einfach als OUT_OF_SERVICE und beeinträchtigt den Anwendungskontext in keiner Weise. Dies ermöglicht ein ordnungsgemäßes Herunterfahren und bedeutet, dass der Dienst bei Bedarf für einige Zeit außer Betrieb genommen und dann wieder zum Leben erweckt werden kann. Der Nachteil ist, dass die JVM nicht gestoppt wird. Sie müssen dies mit dem
kill
Befehl tun . Da ich alles in Containern laufen lasse, war das für mich keine große Sache, da ich den Container sowieso anhalten und entfernen muss.Nr. 2 und 3 basieren mehr oder weniger auf diesem Beitrag von Andy Wilkinson. Sie arbeiten in eine Richtung - sobald sie ausgelöst werden, schließen sie schließlich den Kontext.
quelle
Es gibt viele Möglichkeiten, eine Federanwendung abzuschalten. Eine ist, close () aufzurufen
ApplicationContext
:Ihre Frage schlägt vor, dass Sie Ihre Anwendung schließen möchten, indem Sie dies tun
Ctrl+C
, was häufig zum Beenden eines Befehls verwendet wird. In diesem Fall...Verwendung
endpoints.shutdown.enabled=true
ist nicht das beste Rezept. Dies bedeutet, dass Sie einen Endpunkt zum Beenden Ihrer Anwendung verfügbar machen. Abhängig von Ihrem Anwendungsfall und Ihrer Umgebung müssen Sie ihn also sichern ...Ctrl+C
sollte in Ihrem Fall sehr gut funktionieren. Ich gehe davon aus, dass Ihr Problem durch das kaufmännische Und (&) verursacht wird. Weitere Erläuterungen:Ein Spring-Anwendungskontext hat möglicherweise einen Shutdown-Hook bei der JVM-Laufzeit registriert. Siehe ApplicationContext-Dokumentation .
Ich weiß nicht, ob Spring Boot diesen Hook automatisch konfiguriert, wie Sie sagten. Ich nehme an, es ist.
Ein
Ctrl+C
, Ihre Shell sendet einINT
Signal an die Vordergrundanwendung. Es bedeutet "Bitte unterbrechen Sie Ihre Ausführung". Die Anwendung kann dieses Signal abfangen und vor seiner Beendigung bereinigen (der von Spring registrierte Hook) oder es einfach ignorieren (schlecht).nohup
ist ein Befehl, der das folgende Programm mit einem Trap ausführt, um das HUP-Signal zu ignorieren. HUP wird verwendet, um das Programm zu beenden, wenn Sie auflegen (schließen Sie beispielsweise Ihre SSH-Verbindung). Darüber hinaus werden die Ausgaben umgeleitet, um zu vermeiden, dass Ihr Programm auf einem verschwundenen TTY blockiert.nohup
ignoriert das INT-Signal NICHT. Es verhindert also NICHT, dassCtrl+C
es funktioniert.Ich gehe davon aus, dass Ihr Problem durch das kaufmännische Und (&) und nicht durch nohup verursacht wird.
Ctrl+C
sendet ein Signal an die Vordergrundprozesse. Das kaufmännische Und bewirkt, dass Ihre Anwendung im Hintergrund ausgeführt wird. Eine Lösung: tunVerwenden Sie
kill -9
oderkill -KILL
ist schlecht, weil die Anwendung (hier die JVM) es nicht abfangen kann, um ordnungsgemäß zu beenden.Eine andere Lösung besteht darin, Ihre Anwendung wieder in den Vordergrund zu stellen. Dann
Ctrl+C
wird es funktionieren. Schauen Sie sich die Bash Job-Steuerung genauer anfg
.quelle
Verwenden Sie die statische
exit()
Methode in der SpringApplication-Klasse, um Ihre Spring-Boot-Anwendung ordnungsgemäß zu schließen.quelle
Spring Boot unterstützt jetzt das ordnungsgemäße Herunterfahren (derzeit in den Vorabversionen 2.3.0.BUILD-SNAPSHOT).
Sie können es aktivieren mit:
https://docs.spring.io/spring-boot/docs/2.3.0.BUILD-SNAPSHOT/reference/html/spring-boot-features.html#boot-features-graceful-shutdown
quelle
Wenn Sie maven verwenden, können Sie das Maven App Assembler-Plugin verwenden .
Das Daemon-Mojo (das JSW einbettet ) gibt ein Shell-Skript mit dem Argument start / stop aus. Das
stop
wird Ihre Spring-Anwendung ordnungsgemäß herunterfahren / beenden.Das gleiche Skript kann verwendet werden, um Ihre Maven-Anwendung als Linux-Dienst zu verwenden.
quelle
Wenn Sie sich in einer Linux-Umgebung befinden, müssen Sie lediglich einen Symlink zu Ihrer JAR-Datei aus /etc/init.d/ erstellen.
Dann können Sie die Anwendung wie jeden anderen Dienst starten
So schließen Sie die Anwendung
Auf diese Weise wird die Anwendung nicht beendet, wenn Sie das Terminal verlassen. Und die Anwendung wird ordnungsgemäß mit dem Befehl stop heruntergefahren.
quelle