В документе Spring Boot Document они сказали, что «каждое приложение SpringApplication будет регистрировать обработчик завершения работы с JVM, чтобы гарантировать, что ApplicationContext корректно закрывается при выходе».
Когда я нажимаю ctrl+c
на команду оболочки, приложение может быть корректно завершено. Если я запускаю приложение на производственной машине, я должен использовать команду
java -jar ProApplicaton.jar
. Но я не могу закрыть терминал оболочки, иначе он закроет процесс.
Если я запустил команду вроде nohup java -jar ProApplicaton.jar &
, я не смогу ctrl+c
ее корректно выключить.
Как правильно запускать и останавливать приложение Spring Boot в производственной среде?
linux
spring
spring-boot
Крис
источник
источник
kill -SIGTERM <PID>
должно помочь.Ответы:
Если вы используете модуль исполнительного механизма, вы можете закрыть приложение через
JMX
или,HTTP
если конечная точка включена.добавить в
application.properties
:Будет доступен следующий URL:
/actuator/shutdown
- Разрешает корректное завершение работы приложения (по умолчанию отключено).В зависимости от того, как отображается конечная точка, чувствительный параметр может использоваться как подсказка безопасности.
Например, чувствительные конечные точки потребуют имя пользователя и пароль при доступе к ним
HTTP
(или просто отключены, если веб-безопасность не включена).Из документации по загрузке Spring
источник
Вот еще один вариант, который не требует изменения кода или открытия конечной точки завершения работы. Создайте следующие сценарии и используйте их для запуска и остановки вашего приложения.
start.sh
Запускает ваше приложение и сохраняет идентификатор процесса в файле
stop.sh
Останавливает ваше приложение, используя сохраненный идентификатор процесса
start_silent.sh
Если вам нужно запустить приложение с помощью ssh с удаленного компьютера или конвейера CI, используйте этот сценарий вместо этого для запуска приложения. Непосредственное использование start.sh может привести к зависанию оболочки.
После, например. повторное развертывание вашего приложения, вы можете перезапустить его, используя:
источник
nohup
вы можете просто объединить командыЧто касается ответа @Jan-Philippe Bond,
вот быстрый пример maven для пользователя maven для настройки конечной точки HTTP для выключения веб-приложения с весенней загрузкой с помощью spring-boot-starter-actator, чтобы вы могли скопировать и вставить:
1.Maven pom.xml:
2.application.properties:
Все конечные точки перечислены здесь :
3. Отправьте метод публикации, чтобы закрыть приложение:
Примечание по безопасности:
если вам нужен метод выключения, защищенный аутентификацией, вам также может потребоваться
настроить детали :
источник
server.contextPath=/appName
в свой application.properties Итак, теперь команда для выключения будет выглядеть так:curl -X POST localhost:8080/appName/shutdown
Надеюсь, это может кому-то помочь. Из-за этой ошибки мне пришлось много бороться.endpoints.shutdown.enabled=true management.security.enabled=false
.Вы можете заставить приложение springboot записывать PID в файл, и вы можете использовать файл pid для остановки или перезапуска или получения статуса с помощью сценария bash. Чтобы записать PID в файл, зарегистрируйте слушателя SpringApplication с помощью ApplicationPidFileWriter, как показано ниже:
Затем напишите сценарий bash для запуска приложения весенней загрузки. Ссылка .
Теперь вы можете использовать сценарий для запуска, остановки или перезапуска.
источник
Кажется, что во всех ответах отсутствует тот факт, что вам может потребоваться выполнить некоторую часть работы скоординированно во время плавного завершения работы (например, в корпоративном приложении).
@PreDestroy
позволяет выполнять код выключения в отдельных bean-компонентах. Что-то более сложное могло бы выглядеть так:источник
Я не показываю никаких конечных точек и запускаю ( с nohup в фоновом режиме и без файлов, созданных с помощью nohup ) и останавливаюсь с помощью сценария оболочки (с изящным KILL PID и принудительно уничтожаю, если приложение все еще работает через 3 минуты ). Я просто создаю исполняемый файл jar и использую средство записи файла PID для записи файла PID и сохраняю Jar и Pid в папке с тем же именем, что и имя приложения, а сценарии оболочки также имеют то же имя с началом и остановкой в конце. Я также вызываю эти сценарии остановки и запуска через конвейер Дженкинса. Пока проблем нет. Идеально работает для 8 приложений (очень общие сценарии и легко применимы для любого приложения).
Основной класс
YML-ФАЙЛ
Вот стартовый скрипт (start-appname.sh):
Вот сценарий остановки (stop-appname.sh):
источник
Spring Boot предоставил несколько прослушивателей приложений, в то время как попытка создать контекст приложения, одним из них является ApplicationFailedEvent. Мы можем использовать, чтобы узнать, инициализирован ли контекст приложения или нет.
Добавьте к вышеупомянутому классу слушателя в SpringApplication.
источник
Начиная с Spring Boot 2.3 и новее, есть встроенный механизм плавного завершения работы .
Pre-Spring Boot 2.3 , нет готового механизма плавного завершения работы. Некоторые стартеры с весенней загрузкой предоставляют эту функциональность:
Я автор nr. 1. Стартер называется «Hiatus for Spring Boot». Он работает на уровне балансировщика нагрузки, т.е. просто помечает службу как OUT_OF_SERVICE, никоим образом не влияя на контекст приложения. Это позволяет выполнить плавное завершение работы и означает, что при необходимости службу можно на некоторое время вывести из эксплуатации, а затем снова запустить. Обратной стороной является то, что он не останавливает JVM, вам придется делать это с помощью
kill
команды. Поскольку я запускаю все в контейнерах, для меня это не было проблемой, потому что мне все равно придется останавливать и снимать контейнер.№№ 2 и 3 более или менее основаны на этой публикации Энди Уилкинсона. Они работают односторонне - однажды срабатывая, они в конечном итоге закрывают контекст.
источник
SpringApplication неявно регистрирует перехватчик выключения в JVM, чтобы гарантировать корректное закрытие ApplicationContext при выходе. Это также вызовет все методы bean-компонентов, аннотированные
@PreDestroy
. Это означает, что нам не нужно явно использоватьregisterShutdownHook()
метод aConfigurableApplicationContext
в загрузочном приложении, как мы должны это делать в приложении ядра Spring.источник
@PostConstruct
и@PreDestroy
я использовалinitMethod
иdestroyMethod
атрибуты в@Bean
аннотации. Так что для этого примера:@Bean(initMethod="init", destroyMethod="destroy")
.@PreDestroy
могут не знать некоторые разработчики, заключается в том, что такие методы вызываются только для bean-компонентов с областью действия Singleton. Разработчики должны управлять частью очистки жизненного цикла bean-компонента для других областей видимостиЭто много способов закрыть приложение Spring. Один из них - вызвать close () для
ApplicationContext
:Ваш вопрос предполагает, что вы хотите закрыть свое приложение, выполнив
Ctrl+C
, что часто используется для завершения команды. В таком случае...Использовать
endpoints.shutdown.enabled=true
не лучший рецепт. Это означает, что вы открываете конечную точку для завершения вашего приложения. Итак, в зависимости от вашего варианта использования и вашей среды вам нужно будет защитить его ...Ctrl+C
должен очень хорошо работать в вашем случае. Я предполагаю, что ваша проблема вызвана амперсандом (&) Дополнительные объяснения:Контекст приложения Spring может зарегистрировать перехватчик выключения во время выполнения JVM. См. Документацию ApplicationContext .
Я не знаю, настраивает ли Spring Boot этот хук автоматически, как вы сказали. Я так понимаю.
На
Ctrl+C
, ваша оболочка посылаетINT
сигнал к приложению переднего плана. Это означает «пожалуйста, прервите исполнение». Приложение может перехватить этот сигнал и выполнить очистку до его завершения (ловушка, зарегистрированная Spring) или просто проигнорировать его (плохо).nohup
это команда, которая выполняет следующую программу с ловушкой для игнорирования сигнала HUP. HUP используется для завершения программы, когда вы кладете трубку (например, закрытие ssh-соединения). Более того, он перенаправляет выходные данные, чтобы ваша программа не блокировалась на исчезнувшем TTY.nohup
НЕ игнорирует сигнал INT. Так чтоCtrl+C
работать НЕ мешает .Я предполагаю, что ваша проблема вызвана амперсандом (&), а не nohup.
Ctrl+C
посылает сигнал процессам переднего плана. Амперсанд заставляет ваше приложение работать в фоновом режиме. Одно решение: сделатьИспользование
kill -9
илиkill -KILL
- это плохо, потому что приложение (здесь JVM) не может перехватить его для корректного завершения.Другое решение - вернуть ваше приложение на передний план. Тогда
Ctrl+C
будет работать. Взгляните на Bash Job control, точнее наfg
.источник
Используйте статический
exit()
метод в классе SpringApplication для изящного закрытия приложения весенней загрузки.источник
Spring Boot теперь поддерживает плавное завершение работы (в настоящее время в предварительных версиях 2.3.0.BUILD-SNAPSHOT)
Вы можете включить его с помощью:
https://docs.spring.io/spring-boot/docs/2.3.0.BUILD-SNAPSHOT/reference/html/spring-boot-features.html#boot-features-graceful-shutdown
источник
Если вы используете maven, вы можете использовать плагин ассемблера Maven App .
Демон mojo (который внедряет JSW ) выводит сценарий оболочки с аргументом start / stop. Это
stop
изящно завершит / завершит работу вашего приложения Spring.Тот же сценарий можно использовать для использования вашего приложения maven в качестве службы Linux.
источник
Если вы находитесь в среде Linux, все, что вам нужно сделать, это создать символическую ссылку на ваш файл .jar из /etc/init.d/
Затем вы можете запустить приложение, как и любой другой сервис.
Чтобы закрыть приложение
Таким образом, приложение не завершится после выхода из терминала. И приложение завершится изящно с командой остановки.
источник