W dokumencie Spring Boot Document napisali, że „Każda aplikacja SpringApplication zarejestruje punkt zaczepienia zamykania systemu w JVM, aby zapewnić prawidłowe zamknięcie ApplicationContext przy zamykaniu”.
Kiedy klikam ctrl+c
polecenie powłoki, aplikację można bezpiecznie zamknąć. Jeśli uruchamiam aplikację na maszynie produkcyjnej, muszę użyć polecenia
java -jar ProApplicaton.jar
. Ale nie mogę zamknąć terminala powłoki, w przeciwnym razie zamknie proces.
Jeśli uruchomię polecenie w stylu nohup java -jar ProApplicaton.jar &
, nie mogę go użyć ctrl+c
do zamknięcia go z wdziękiem.
Jaki jest prawidłowy sposób uruchamiania i zatrzymywania aplikacji Spring Boot w środowisku produkcyjnym?
linux
spring
spring-boot
Chris
źródło
źródło
kill -SIGTERM <PID>
powinno załatwić sprawę.Odpowiedzi:
Jeśli używasz modułu wykonawczego, możesz zamknąć aplikację za pomocą
JMX
lubHTTP
jeśli punkt końcowy jest włączony.dodaj do
application.properties
:Dostępny będzie następujący adres URL:
/actuator/shutdown
- Zezwala na bezpieczne zamykanie aplikacji (domyślnie wyłączone).W zależności od sposobu ujawnienia punktu końcowego parametr wrażliwy może służyć jako wskazówka dotycząca bezpieczeństwa.
Na przykład wrażliwe punkty końcowe będą wymagały nazwy użytkownika / hasła, gdy zostaną udostępnione
HTTP
(lub po prostu wyłączone, jeśli zabezpieczenia internetowe nie są włączone).Z dokumentacji rozruchu Spring
źródło
Oto kolejna opcja, która nie wymaga zmiany kodu ani ujawniania punktu końcowego zamykania. Utwórz następujące skrypty i użyj ich do uruchamiania i zatrzymywania aplikacji.
start.sh
Uruchamia aplikację i zapisuje identyfikator procesu w pliku
stop.sh
Zatrzymuje aplikację przy użyciu zapisanego identyfikatora procesu
start_silent.sh
Jeśli chcesz uruchomić aplikację przy użyciu ssh z maszyny zdalnej lub potoku CI, użyj tego skryptu, aby uruchomić aplikację. Bezpośrednie użycie start.sh może spowodować zawieszenie się powłoki.
Po np. ponownie / wdrażając swoją aplikację, możesz ją zrestartować za pomocą:
źródło
nohup
, możesz po prostu scalić poleceniaJeśli chodzi o odpowiedź @ Jean-Philippe Bonda,
oto szybki przykład Mavena dla użytkownika maven, aby skonfigurować punkt końcowy HTTP, aby zamknąć aplikację internetową rozruchu sprężynowego za pomocą sprężyny rozruchowej-siłownika, aby można było skopiować i wkleić:
1.Maven pom.xml:
2. application.properties:
Wszystkie punkty końcowe są wymienione tutaj :
3.Wyślij post, aby zamknąć aplikację:
Uwaga dotycząca bezpieczeństwa:
jeśli potrzebujesz zabezpieczonej metody zamykania, możesz również potrzebować
skonfiguruj szczegóły :
źródło
server.contextPath=/appName
do pliku application.properties, teraz polecenie zamknięcia będzie wyglądać następująco :curl -X POST localhost:8080/appName/shutdown
Mam nadzieję, że może to komuś pomóc. Musiałem dużo walczyć z powodu tego błędu.endpoints.shutdown.enabled=true management.security.enabled=false
.Możesz sprawić, by aplikacja springboot zapisywała PID do pliku i możesz użyć pliku pid do zatrzymania lub ponownego uruchomienia lub uzyskania statusu za pomocą skryptu bash. Aby zapisać PID do pliku, zarejestruj odbiornik w SpringApplication za pomocą ApplicationPidFileWriter, jak pokazano poniżej:
Następnie napisz skrypt bash, aby uruchomić aplikację rozruchową wiosny. Odniesienie .
Teraz możesz użyć skryptu do uruchomienia, zatrzymania lub ponownego uruchomienia.
źródło
Wydaje się, że we wszystkich odpowiedziach brakuje faktu, że pewna część pracy może być konieczna w skoordynowany sposób podczas bezpiecznego zamykania systemu (na przykład w aplikacji korporacyjnej).
@PreDestroy
umożliwia wykonanie kodu zamknięcia w poszczególnych komponentach bean. Coś bardziej wyrafinowanego wyglądałoby tak:źródło
Nie ujawniam żadnych punktów końcowych i uruchamiam ( z nohup w tle i bez plików utworzonych przez nohup ) i zatrzymuję się za pomocą skryptu powłoki (z wdziękiem KILL PID i wymuszeniem zabicia, jeśli aplikacja nadal działa po 3 minutach ). Po prostu tworzę wykonywalny jar i używam programu do zapisywania plików PID, aby zapisać plik PID i przechowywać Jar i Pid w folderze o tej samej nazwie, co nazwa aplikacji, a skrypty powłoki również mają tę samą nazwę z początkiem i końcem. Nazywam te skrypty zatrzymujące i uruchamiające skrypt również przez potok Jenkinsa. Na razie brak problemów. Doskonale działa dla 8 aplikacji (bardzo ogólne skrypty i łatwe do zastosowania w dowolnej aplikacji).
Klasa główna
PLIK YML
Oto skrypt startowy (start-appname.sh):
Oto skrypt zatrzymujący (stop-appname.sh):
źródło
Spring Boot dostarczył kilka nasłuchiwania aplikacji podczas próby stworzenia kontekstu aplikacji, jednym z nich jest ApplicationFailedEvent. Możemy użyć, aby wiedzieć, czy kontekst aplikacji został zainicjowany, czy nie.
Dodaj do powyższej klasy detektora do SpringApplication.
źródło
Od wersji Spring Boot 2.3 i nowszych istnieje wbudowany wdzięczny mechanizm zamykania .
Pre-Spring Boot 2.3 , nie ma gotowego do użycia wdzięcznego mechanizmu zamykania. Niektóre rozruszniki sprężynowe zapewniają tę funkcjonalność:
Jestem autorem nr. 1. Starter nosi nazwę „Hiatus for Spring Boot”. Działa na poziomie load balancera, tzn. Po prostu oznacza usługę jako OUT_OF_SERVICE, nie ingerując w żaden sposób w kontekst aplikacji. Pozwala to na płynne zamknięcie i oznacza, że w razie potrzeby usługa może zostać wyłączona na pewien czas, a następnie przywrócona do życia. Wadą jest to, że nie zatrzymuje JVM, będziesz musiał to zrobić za pomocą
kill
polecenia. Ponieważ prowadzę wszystko w kontenerach, nie było to dla mnie nic wielkiego, bo i tak będę musiał się zatrzymać i wyjąć kontener.Numery 2 i 3 są mniej więcej oparte na tym poście Andy'ego Wilkinsona. Działają jednokierunkowo - po uruchomieniu zamykają kontekst.
źródło
SpringApplication niejawnie rejestruje hak zamykania systemu w maszynie JVM, aby zapewnić prawidłowe zamknięcie ApplicationContext przy zamykaniu. Spowoduje to również wywołanie wszystkich metod bean z adnotacjami
@PreDestroy
. Oznacza to, że nie musimy jawnie używaćregisterShutdownHook()
metody aConfigurableApplicationContext
w aplikacji rozruchowej, tak jak w przypadku aplikacji Spring Core.źródło
@PostConstruct
i@PreDestroy
użyłem atrybutówinitMethod
idestroyMethod
w@Bean
adnotacji. Tak więc w tym przykładzie:@Bean(initMethod="init", destroyMethod="destroy")
.@PreDestroy
niewielu deweloperów może nie wiedzieć, polega na tym, że takie metody są wywoływane tylko w przypadku ziaren o zasięgu Singleton. Deweloperzy muszą zarządzać oczyszczaną częścią cyklu życia fasoli dla innych zakresówIstnieje wiele sposobów zamykania aplikacji sprężynowej. Jednym z nich jest wywołanie funkcji close () na
ApplicationContext
:Twoje pytanie sugeruje, że chcesz zamknąć aplikację, robiąc to
Ctrl+C
, co jest często używane do zakończenia polecenia. W tym przypadku...Stosowanie
endpoints.shutdown.enabled=true
nie jest najlepszym przepisem. Oznacza to, że udostępniasz punkt końcowy, aby zamknąć aplikację. Tak więc, w zależności od przypadku użycia i środowiska, będziesz musiał je zabezpieczyć ...Ctrl+C
powinien działać bardzo dobrze w twoim przypadku. Zakładam, że przyczyną problemu jest znak & (&) Więcej wyjaśnień:Kontekst aplikacji Spring mógł zarejestrować punkt zaczepienia zamknięcia systemu w środowisku wykonawczym maszyny JVM. Zobacz dokumentację ApplicationContext .
Nie wiem, czy Spring Boot skonfiguruje ten hak automatycznie, jak powiedziałeś. Zakładam, że tak.
W dniu
Ctrl+C
twoja powłoka wysyłaINT
sygnał do aplikacji pierwszego planu. To znaczy „proszę, przerwij wykonanie”. Aplikacja może przechwycić ten sygnał i wyczyścić go przed jego zakończeniem (zaczep zarejestrowany przez Spring) lub po prostu go zignorować (źle).nohup
to polecenie, które wykonuje następujący program z pułapką, aby zignorować sygnał HUP. HUP jest używany do kończenia programu po rozłączeniu się (na przykład zamknięcie połączenia ssh). Ponadto przekierowuje dane wyjściowe, aby uniknąć blokowania się programu na zaginionym TTY.nohup
NIE ignoruje sygnału INT. Więc to NIE przeszkadzaCtrl+C
w pracy.Zakładam, że przyczyną problemu jest znak „&”, a nie „nohup”.
Ctrl+C
wysyła sygnał do procesów pierwszoplanowych. Znak ampersand powoduje uruchomienie aplikacji w tle. Jedno rozwiązanie: zróbUżyj
kill -9
lubkill -KILL
jest złe, ponieważ aplikacja (w tym przypadku JVM) nie może jej przechwycić, aby zakończyć w sposób wdzięczny.Innym rozwiązaniem jest przywrócenie aplikacji na pierwszy plan. Wtedy
Ctrl+C
zadziała. Przyjrzyj się sterowaniu Bash Job, a dokładniejfg
.źródło
Użyj
exit()
metody statycznej w klasie SpringApplication, aby bezpiecznie zamknąć aplikację rozruchową wiosny.źródło
Spring Boot obsługuje teraz bezpieczne zamykanie (obecnie w wersjach wstępnych 2.3.0.BUILD-SNAPSHOT)
Możesz to włączyć za pomocą:
https://docs.spring.io/spring-boot/docs/2.3.0.BUILD-SNAPSHOT/reference/html/spring-boot-features.html#boot-features-graceful-shutdown
źródło
Jeśli używasz mavena, możesz użyć wtyczki Maven App assembler .
Demon mojo (który osadza JSW ) wyświetli skrypt powłoki z argumentem start / stop. Z
stop
wdziękiem zamknie / zabije Twoją aplikację Spring.Ten sam skrypt może służyć do używania aplikacji maven jako usługi linuxowej.
źródło
Jeśli pracujesz w środowisku linuxowym, wszystko co musisz zrobić, to utworzyć dowiązanie symboliczne do pliku .jar z wnętrza /etc/init.d/
Następnie możesz uruchomić aplikację jak każdą inną usługę
Aby zamknąć aplikację
W ten sposób aplikacja nie zostanie zakończona po wyjściu z terminala. Aplikacja zamknie się płynnie po poleceniu zatrzymania.
źródło