Как остановить spring boot приложение
В данной статье я попробую расписать все шаги, которые потребуются для создания небольшого проекта на Spring Boot и развертывания его на боевом сервере.
Не будем тянуть долгими прелюдиями о философии java и spring'а, и сразу приступим к делу.
Для начала нам необходимо создать каркас приложения, внедрив туда весь необходимый зоопарк технологий(как минимум Spring, JPA, JDBC). До появления spring boot нужно было потратить на это немало времени, если конечно у вас не было рабочей заготовки в закромах кода. И именно сложность создания подобного каркаса, как мне кажется, останавливает многих от разработки небольших веб-проектов на java. Конечно, когда-то был хромой spring roo, который мог создать подобный каркас в ущерб производительности(привет аспектам), но даже с ним количество и сложность конфигурационных файлов заставляли долго медитировать над ними неподготовленного разработчика. Однако теперь с приходом Boot и Spring 4 жизнь стала немного проще и количество конфигурационных файлов заметно уменьшилось.
Если у вас есть Intellij Idea 14.1, то проблем с каркасом возникнуть вообще не должно, можно все сделать через специальный мастер создания проектов(File-New-Project. -Spring Initializr). Далее останется только указать названия проектов, выбрать интересующие нас технологии(Web, JDBC, JPA, PostgreSQL) и создать проект.
Если же у вас нет данной IDE, то скачиваем Spring Boot CLI, следуем инструкции в INSTALL.txt. Нужно задать системную переменную SPRING_HOME(путь к папке со Spring Boot, не к папке bin!) и добавить путь к SPRING_HOME/bin в системную переменную PATH на windows.
Итак, консоль спринга настроили, теперь самое время создать проект. Сделать это можно следующей командой:
UPDATE
Кроме того, как написали в комментариях, существует еще веб-конструктор: start.spring.io
Далее импортируем получившийся каркас в любимую IDE и начинаем его модифицировать под наши нужды.
Для начала добавим в каталог src/main папку webapps. Все веб-ресурсы мы будем создавать в ней, а не в папке resources, как хочет того спринг. Дело в том, что если мы будем создавать файлы в папке resources, то тогда мы лишимся возможности видеть изменения, сделанные в наших веб-ресурсах, без перезагрузки сервера. А это может быть неприятно, когда ради того, чтобы посмотреть изменившийся текст на веб-странице приходится перезапускать веб-сервер.
Теперь в папке webapps создаем файл index.html и папки css, js, font, images, в которые будем класть соответствующие ресурсы.
Для примера сделаем самый простой каркас index.html:
Изменим файл pom.xml
Должно получиться что-то подобное:
Мы используем postgresql 9.4(тоже неплохо бы установить его локально на свою машину). Connection pool для взаимодействия с базой данных мы берем самый модный и производительный (HikariCP). Кроме того, мы используем специальный плагин, который, когда мы будем генерировать итоговый jar'ник, перенесет все наши данные из webapp в resources/static, как того хочет spring boot. В противном случае вы не сможете увидеть все те веб-страницы, что создадите в папке webapps, когда запустите jar-ник.
Добавим пакет config и создадим в нем класс JpaConfig:
Кроме того, добавим в файл application.properties следующие строчки:
И наконец в Application.java меняем строку инициализации на следующую:
Тем самым мы настроили подключение к СУБД PostgreSQL.
Не забываем создать саму базу данных и простенькую таблицу в ней. Сделать это удобнее всего через PgAdmin.
Создав в ней пустую базу yourapp_data, выполняем скрипт создания таблицы:
Теперь настало время немного заняться начинкой нашего проекта. А именно добавить какую-нибудь сущность БД и научиться с ней работать, получая с клиента данные для ее формирования и отправляя клиенту же данные об уже созданных сущностях.
Создаем пакеты controller, entity, repository, service, utils.
В пакете entity создаем интерфейс:
Аннотации JPA и Hibernate в данном примере использовать не будем, так как эти технологии сильно замедляют работу(запрос может выполняться в 10 раз медленнее, чем на чистом jdbc), а так как у нас нет сильно сложных сущностей, для которых реально может потребоваться ORM, то воспользуемся обычным jdbcTemplate.
Создаем интерфейс репозитория:
И его реализацию:
Вместо уже упомянутого jdbcTemplate, мы, как видите, используем JdbcOperations, который является его интерфейсом. Нам приходится использовать везде интерфейсы, отделяя их от реализации, так как, во-первых это стильно, модно, молодежно, а во-вторых, spring в нашем случае использует стандартный jdk'шный Proxy для наших объектов, поэтому напрямую инжектить реализацию не получиться, пока мы не введем полноценные аспекты и AspectJ compile-time weaving. В нашем случае этого и не требуется, чтобы не перегружать приложение.
Осталось уже немного. Создаем наш сервис(мы же хорошие разработчики и должны отделить бизнес-логику от логики работы с СУБД?).
Отлично. Теперь создаем пару вспомогательных классов, необходимых для реализации контроллера:
Это наша реализация Exception'а. Может пригодиться в будущем, хотя и не обязательна, но на нее завязан следующий класс:
Если мы словили такую ошибку в нашем контроллере, то она будет обработана дополнительно в этом методе.
Наконец напишем небольшой классик, который будет формировать структуру данных для передачи на клиент:
Все, со вспомогательными классами закончили. Осталось написать наш контроллер. Он будет простым, как пробка:
В нем два метода — сохранить полученные данные и выдать порцию случайных данных на клиент. Контроллер унаследован от созданного нами ранее ExceptionHandlerController. Обработка исключений написана только как шаблон и нуждается в соответствующей доработки под себя.
Итак, основная часть серверного кода написана, осталось проверить его работу на клиенте. Для этого нужно доработать наш файл index.html и заодно добавить библиотеку jquery в каталог js.
index.html:
Однако рано или поздно вы сотворите желаемое и встанет вопрос о том, как донести ваше детище в массы. Об этом будет вторая часть статьи.
Этот сервис позволит бесплатно зарегистрировать домен в зонах .tk, .ml, .ga, .cf, .gq
Да, не самые лучшие зоны, но:
Отлично, у нас есть сервер, пора залить на него наш проект.
Для начала собираем проект maven'ом. Сделать это можно через IDE или же на худой конец зайдя в корневую директорию проекта и введя команду mvn clean install(путь к мавену должен быть прописан в системой переменной path на Windows). После выполнения команды собранный jar'ник помещается в локальный репозиторий (по умолчанию именуемый .m2), откуда его можно стянуть для отправки на сервер.
Для передачи файла на сервер используем WinSCP, если вы работаете под Windows.
Далее заходим на наш сервер, используя putty на Windows или ssh на Linux.
Переходим в директорию, куда был скопирован наш jar-ник и пробуем его запустить командой java -jar youapp.jar
Скорей всего, не получилось. А все почему? Наш проект был создан на java 8, а какая java стоит на сервере, можно узнать с помощью команды java -version. И скорей всего это либо 6, либо 7.
Но не будем унывать, поставим себе новую версию:
Теперь настала очередь postgres'а. До этого мы использовали локальную версию на машине разработчика, теперь пришло время поставить СУБД на сервер.
Для этого сначала выполняем магическую последовательность команд:
Далее выполняем команду входа в psql:
И выходим c помощью команды \q
Затем редактируем файл /etc/postgresql/9.4/main/pg_hba.conf
Должны быть добавлены две новых строчки и изменена одна строка для 127.0.0.1 следующим образом:
Я намеренно изменил md5 на trust, так как лично у меня были проблемы с запуском проекта, тем самым отключив проверку пароля для заданных адресов. Возможно у вас их не будет.
Теперь все настроено. Хотя тюнинговать постгрес можно до бесконечности, но ведь у нас всего лишь маленький проект, а значит, пока оставим как есть.
Перезапускаем postgres: и проверяем его работу.
Всё, с настройкой postgres'а закончили, что у нас дальше по сценарию?
Как уже было отмечено ранее, для запуска собранного jar'ника вполне достаточно команды java -jar youapp.jar
Однако при подобном запуске для того, чтобы зайти на сайт извне, придется прописывать порт(по умолчанию 8080). Чтобы пользователи смогли зайти на сайт, просто введя его адрес, то нам потребуется прокси сервер. В качестве него можно взять nginx, который нужно будет предварительно настроить.
В моем случае корневой директорией nginx была /etc/nginx. Там нам в первую очередь потребуется изменить файл /sites_available/default следующим образом:
Однако и это еще не все. Необходимо также модифицировать наш проект, чтобы он поддерживал настроенный нами прокси. Благо сделать это не трудно, достаточно лишь в application.properties добавить строки(не забудьте залить новую версию с изменениями):
Теперь можно запустить nginx командой service nginx start и затем попробовать запустить наш проект. Он будет доступен по ссылке сайта, либо же, если вы еще не приобрели домен, то по его ip-адресу, без указания порта.
Остался еще один небольшой штрих. Немного неудобно всегда стартовать проект тем способом, который был описан выше. Неплохо бы, чтобы при старте проекта консоль ввода на сервере освобождалась, приложение не закрывалось бы после выхода из ssh-сессии и чтобы где-нибудь велись логи приложения. Сделать это можно с помощью команды nohup. Предварительно создаем bash-скрипт, называя его script.sh:
Прописываем ему право на исполнение:
И запускаем командой:
Все, приложение запущено.
Чтобы остановить приложение, можно либо воспользоваться командой pkill -9 java(при условии, что это единственное java-приложение, запущенное на сервере), либо с помощью утилиты htop, выделив этот процесс, нажав кнопку F9, выбрав слева в списке SIGKILL и нажав enter. На заметку: иногда не срабатывает с первого раза и процедуру приходится повторять.
Теперь, если все сделано правильно, можно открыть сайт нашего проекта в браузере и насладиться результатом.
В документе Spring Boot Document они сказали, что «каждое приложение SpringApplication будет регистрировать обработчик завершения работы с JVM, чтобы гарантировать, что ApplicationContext корректно закрывается при выходе».
Когда я нажимаю ctrl+c на команду оболочки, приложение может быть корректно завершено. Если я запускаю приложение на производственной машине, я должен использовать команду java -jar ProApplicaton.jar . Но я не могу закрыть терминал оболочки, иначе он закроет процесс.
Если я запустил команду вроде nohup java -jar ProApplicaton.jar & , я не смогу ctrl+c ее корректно выключить.
Как правильно запускать и останавливать приложение Spring Boot в производственной среде?
Какой сигнал мне использовать, я не думаю, что kill -9 - хорошая идея, верно? Вот почему я указал вам на эту ветку . Но что-то вроде kill -SIGTERM <PID> должно помочь. kill $ (lsof -ti tcp: <port>) - на случай, если вы не хотите использовать актуатор и вам нужно быстрое убийстводобавить в application.properties :
Будет доступен следующий URL:
/actuator/shutdown - Разрешает корректное завершение работы приложения (по умолчанию отключено).
В зависимости от того, как отображается конечная точка, чувствительный параметр может использоваться как подсказка безопасности.
Я не хочу включать модуль исполнительного механизма. Но я обнаружил, что в моем журнале консоли Spring Boot печатает PID в первой строке. Есть ли способ разрешить Spring Boot печатать PID в другом файле без добавления модуля привода (ApplicationPidListener)?Вот еще один вариант, который не требует изменения кода или открытия конечной точки завершения работы. Создайте следующие сценарии и используйте их для запуска и остановки вашего приложения.
start.sh
Запускает ваше приложение и сохраняет идентификатор процесса в файле
stop.sh
Останавливает ваше приложение, используя сохраненный идентификатор процесса
start_silent.sh
Если вам нужно запустить приложение с помощью ssh с удаленного компьютера или конвейера CI, используйте этот сценарий вместо этого для запуска приложения. Непосредственное использование start.sh может привести к зависанию оболочки.
После, например. повторное развертывание вашего приложения, вы можете перезапустить его, используя:
Это должен быть ответ. Я только что подтвердил, что сигнал выключения 15 сообщает пружине, что она изящно выключается. Почему бы вам не вызвать выполнение java-jar с помощью nohup внутри start.sh, а не вызывать выполнение java-jar внутри start.sh, которое вызывается с помощью nohup внутри другого сценария внешней оболочки ?? @AnandVarkeyPhilips Единственная причина в том, что я иногда вызываю start.sh из командной строки для целей тестирования, но если вам всегда нужно, nohup вы можете просто объединить команды @Jens, спасибо за информацию. Можете ли вы сказать, что вы делаете это: foo.out 2> foo.err </ dev / null &Что касается ответа @Jan-Philippe Bond,
Все конечные точки перечислены здесь :
3. Отправьте метод публикации, чтобы закрыть приложение:
Примечание по безопасности:
если вам нужен метод выключения, защищенный аутентификацией, вам также может потребоваться
Обратите внимание: если бы я включил что-то вроде server.contextPath=/appName в свой application.properties Итак, теперь команда для выключения будет выглядеть так: curl -X POST localhost:8080/appName/shutdown Надеюсь, это может кому-то помочь. Из-за этой ошибки мне пришлось много бороться. В Spring Boot 1.5.8 рекомендуется, если без защиты, иметь в application.properties endpoints.shutdown.enabled=true management.security.enabled=false .Вы можете заставить приложение springboot записывать PID в файл, и вы можете использовать файл pid для остановки или перезапуска или получения статуса с помощью сценария bash. Чтобы записать PID в файл, зарегистрируйте слушателя SpringApplication с помощью ApplicationPidFileWriter, как показано ниже:
Затем напишите сценарий bash для запуска приложения весенней загрузки. Ссылка .
Теперь вы можете использовать сценарий для запуска, остановки или перезапуска.
Кажется, что во всех ответах отсутствует тот факт, что вам может потребоваться выполнить некоторую часть работы скоординированно во время плавного завершения работы (например, в корпоративном приложении).
@PreDestroy позволяет выполнять код выключения в отдельных bean-компонентах. Что-то более сложное могло бы выглядеть так:
Это как раз то, что мне нужно. После выполнения приложения нажмите ctrl-c. Спасибо @MichalЯ не показываю никаких конечных точек и запускаю ( с nohup в фоновом режиме и без файлов, созданных с помощью nohup ) и останавливаюсь с помощью сценария оболочки (с изящным KILL PID и принудительно уничтожаю, если приложение все еще работает через 3 минуты ). Я просто создаю исполняемый файл jar и использую средство записи файла PID для записи файла PID и сохраняю Jar и Pid в папке с тем же именем, что и имя приложения, а сценарии оболочки также имеют то же имя с началом и остановкой в конце. Я также вызываю эти сценарии остановки и запуска через конвейер Дженкинса. Пока проблем нет. Идеально работает для 8 приложений (очень общие сценарии и легко применимы для любого приложения).
Вот стартовый скрипт (start-appname.sh):
Вот сценарий остановки (stop-appname.sh):
Spring Boot предоставил несколько прослушивателей приложений, в то время как попытка создать контекст приложения, одним из них является ApplicationFailedEvent. Мы можем использовать, чтобы узнать, инициализирован ли контекст приложения или нет.
Добавьте к вышеупомянутому классу слушателя в SpringApplication.
[@ user3137438], чем он отличается от входа в аннотацию pre destroy?Начиная с 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() метод a ConfigurableApplicationContext в загрузочном приложении, как мы должны это делать в приложении ядра 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 этот хук автоматически, как вы сказали. Я так понимаю.
nohup это команда, которая выполняет следующую программу с ловушкой для игнорирования сигнала HUP. HUP используется для завершения программы, когда вы кладете трубку (например, закрытие ssh-соединения). Более того, он перенаправляет выходные данные, чтобы ваша программа не блокировалась на исчезнувшем TTY. nohup НЕ игнорирует сигнал INT. Так что Ctrl+C работать НЕ мешает .
Я предполагаю, что ваша проблема вызвана амперсандом (&), а не nohup. Ctrl+C посылает сигнал процессам переднего плана. Амперсанд заставляет ваше приложение работать в фоновом режиме. Одно решение: сделать
Использование kill -9 или kill -KILL - это плохо, потому что приложение (здесь JVM) не может перехватить его для корректного завершения.
Другое решение - вернуть ваше приложение на передний план. Тогда Ctrl+C будет работать. Взгляните на Bash Job control, точнее на fg .
Фреймворк Spring boot использовался в производственной среде в течение определенного периода времени. Его функция «соглашение больше, чем конфигурация» отражает элегантный и плавный процесс разработки, а также метод запуска развертывания ( java -jar xxx.jar ) Тоже очень элегантно. Но то, как я останавливаю приложение, kill -9 номер процесса , Хоть я и написал сценарий, он все равно казался немного грубым. При таком способе остановки приложения бизнес-логика, обрабатываемая в приложении, будет прервана в момент остановки, что приведет к сбоям в работе. Как избежать этой ситуации? Изящное завершение работы, описанное в этой статье, отлично решит проблему.
00 Предисловие
Что такое плавное завершение работы? Проще говоря, после отправки команды остановки процессу приложения можно гарантировать, что выполняемая бизнес-операция не будет затронута. Шаг после того, как приложение получит команду остановки, должен заключаться в прекращении приема запросов доступа, ожидании завершения обработки полученного запроса и успешном возврате, тогда приложение действительно останавливается.
Как добиться этого идеального метода остановки приложения? Что касается экологии языка Java, поддерживается базовая технология, поэтому мы можем добиться плавного завершения работы каждого веб-контейнера поверх языка Java.
В обычном внешнем tomcat есть сценарий выключения, обеспечивающий элегантный механизм выключения, но мы обнаружили, что веб-контейнер встроен во время использования загрузки Spring (конечно, его также можно использовать извне, но это не рекомендуется), этот способ предоставляется Простой метод запуска приложения и удобный механизм управления очень подходят для микросервисных приложений, но не существует метода постепенного завершения работы, предусмотренного по умолчанию. Это также основная причина этой проблемы.
Достигнуто ли плавное завершение работы приложения, как это проверить? Это требует длительной обработки бизнес-логики, моделирование такой логики должно быть очень простым, с использованием спящего режима потока или длинного цикла. Мой смоделированный код бизнес-логики выглядит следующим образом:
Метод проверки заключается в том, что после запуска бизнес-обработки этого интерфейса время обработки бизнес-логики составляет до 1 минуты, и необходимо инициировать команду остановки до завершения обработки, чтобы проверить, может ли она нормально вернуться. Команда kill, используемая во время проверки: kill -2(Ctrl + C) 、 kill -15 、 kill -9 。
01 Изящное выключение языка Java
Из приведенного выше введения мы обнаружили, что сам язык Java поддерживает плавное завершение работы. Здесь мы сначала расскажем, как обычные приложения Java достигают плавного завершения работы.
Когда мы используем kill PID Когда Java-приложение каким-то образом завершается, JVM получит сигнал остановки, а затем выполнит поток shutdownHook. Пример реализации выглядит следующим образом:
Ключевое предложение Runtime.getRuntime().addShutdownHook(this); Зарегистрируйте ловушку для выключения JVM, эту ловушку можно вызвать в следующих сценариях:
- Программа выходит нормально
- Используйте System.exit ()
- Терминал, использующий Ctrl + C для запуска прерывания
- Завершение работы системы
- Используйте команду Kill pid, чтобы убить процесс
Протестируйте функцию shutdownHook, пример кода:
Запустите тестовый код, а затем отправьте сигнал прерывания, вывод консоли:
Видно, что после получения сигнала прерывания выполняется вся основная функция.
02 actuator/shutdown of Spring boot
Мы знаем способность самой java поддерживать плавное завершение работы, а затем мы обнаружили это в Spring boot. actuator/shutdown Конечная точка управления. Поэтому я возлагал надежды на функцию плавного выключения и начал тест конфигурации.Конфигурация включается следующим образом:
Внедрение конечной точки выключения в официальном документе:
Из этого введения видно, что проект должен поддерживать плавное завершение работы. Но почему сейчас он недостаточно элегантен? В проекте загрузки Spring, размещенном на github, я обнаружил, что естьissueОн открыт уже более двух лет. В нем много обсуждений. Прочитав его, я обнаружил, что нелегко полностью поддерживать плавное завершение работы при загрузке Spring. Во-первых, загрузка Spring поддерживает множество веб-контейнеров, а во-вторых, какая реализация необходима? Это действительно изящное завершение работы, о котором много говорили. Если вы хотите узнать больше студентов, внимательно прочтите этот выпуск.
В этом выпуске также содержится важная информация. Этот вопрос был однажды добавлен к этапу 2.0.0, а затем удален, поскольку он не был завершен. Текущий статус добавлен к этапу 2.1.0. Я тестировал версию 2.0.1, и я с нетерпением жду официального идеального и элегантного плана завершения работы.
03 Пружинный ботинок изящно выключается
Хотя официальный представитель еще не предоставил поддержку для постепенного завершения работы, чтобы уменьшить влияние приостановки процесса на бизнес, мы все же должны предоставить план, который может удовлетворить основные потребности.
Решение для кота:
Код этого решения взят из обсуждения в официальном выпуске. Добавьте эти коды в свой проект загрузки Spring. После перезапуска инициируйте тестовый запрос, а затем отправьте команду kill stop ( kill -2(Ctrl + C) 、 kill -15 ). Результаты теста:
Судя по результатам тестирования, это соответствует нашим потребностям. Конечно, если вы пришлете инструкцию kill -9 , Процесс немедленно остановится.
Решение проблемы отката:
Ссылка на методстатья, Используя ту же тестовую программу, что и tomcat, результаты теста:
04 Конец
В Spring Boot Document они сказали, что «Каждое SpringApplication регистрирует перехватчик завершения работы с JVM, чтобы обеспечить корректное закрытие ApplicationContext при выходе».
Когда я нажимаю ctrl+c в команде Shell, приложение может быть корректно завершено. Если я запускаю приложение на производственном компьютере, я должен использовать команду Java -jar ProApplicaton.jar . Но я не могу закрыть терминал Shell, иначе он закроет процесс.
Если я запускаю команду наподобие Nohup Java -jar ProApplicaton.jar & , я не могу использовать ctrl+c , чтобы корректно завершить ее.
Как правильно запустить и остановить Spring Boot Application в производственной среде?
/shutdown - Позволяет корректно завершить работу приложения (по умолчанию не включено).
Что касается ответа @ Jean-Philippe Bond,
Все конечные точки перечислены здесь :
Примечание по безопасности:
если вам нужен защищенный метод завершения работы, вам также может понадобиться
Вот еще один вариант, который не требует изменения кода или предоставления конечной точки выключения. Создайте следующие сценарии и используйте их для запуска и остановки вашего приложения.
start.sh
Запускает ваше приложение и сохраняет идентификатор процесса в файле
stop.sh
Останавливает ваше приложение, используя сохраненный идентификатор процесса
start_silent.sh
Если вам нужно запустить приложение с помощью ssh с удаленной машины или конвейера CI, используйте этот скрипт вместо этого, чтобы запустить ваше приложение. Использование start.sh напрямую может привести к зависанию Shell.
После например Для повторного развертывания приложения вы можете перезапустить его, используя:
Вы можете сделать приложение Springboot для записи PID в файл, и вы можете использовать файл pid, чтобы остановить или перезапустить или получить статус, используя скрипт bash. Чтобы записать PID в файл, зарегистрируйте прослушиватель SpringApplication с помощью ApplicationPidFileWriter, как показано ниже:
Затем напишите bash-скрипт для запуска приложения весенней загрузки. Ссылка .
Теперь вы можете использовать скрипт для запуска, остановки или перезапуска.
Я не выставляю никаких конечных точек и запускаю ( с Nohup в фоновом режиме и без файлов out, созданных через Nohup ) и останавливаюсь с помощью сценария Shell (с помощью KILL PID изящно и принудительно уничтожаю, если приложение все еще работает через 3 минуты ). Я просто создаю исполняемый jar и использую PID-файл для записи PID-файлов и сохраняю Jar и Pid в папке с тем же именем, что и у имени приложения, а сценарии Shell также имеют одинаковые имена с start и stop в конце. Я вызываю эти сценарии остановки и запускаю сценарий через конвейер jenkins. Пока никаких проблем. Отлично работает для 8 приложений (очень универсальные сценарии и легко применяются для любого приложения).
Вот стартовый скрипт (start-appname.sh):
Вот скрипт остановки (stop-appname.sh):
Spring Boot предоставил несколько прослушивателей приложений при попытке создать контекст приложения, одним из которых является ApplicationFailedEvent. Мы можем использовать, чтобы знать, инициализирован ли контекст приложения, или нет.
Добавьте к вышеупомянутому классу слушателя SpringApplication.
SpringApplication неявно регистрирует ловушку отключения в JVM, чтобы гарантировать, что ApplicationContext будет корректно закрыт при выходе. Это также вызовет все методы bean, аннотированные @PreDestroy . Это означает, что нам не нужно явно использовать метод registerShutdownHook() для ConfigurableApplicationContext в загрузочном приложении, как мы делаем это в весеннем базовом приложении.
Кажется, что во всех ответах отсутствует тот факт, что вам может потребоваться завершить некоторую часть работы согласованным образом во время постепенного завершения работы (например, в корпоративном приложении).
@PreDestroy позволяет выполнить код выключения в отдельных bean-компонентах. Что-то более сложное будет выглядеть так:
Начиная с Spring Boot 1.5, отсутствует механизм изящного выключения из коробки . Некоторые пусковые устройства с пружинной загрузкой предоставляют такую функциональность:
Я автор Nr. 1. Стартер называется «Hiatus for Spring Boot». Он работает на уровне балансировки нагрузки, то есть просто помечает службу как OUT_OF_SERVICE, никоим образом не влияя на контекст приложения. Это позволяет выполнить постепенное отключение и означает, что при необходимости сервис может быть выведен из строя на некоторое время, а затем возвращен к жизни. Недостатком является то, что он не останавливает JVM, вам придется делать это с помощью команды kill . Поскольку я запускаю все в контейнерах, для меня это не имело большого значения, потому что мне все равно придется остановиться и удалить контейнер.
Номера 2 и 3 более или менее основаны на этом посте Энди Уилкинсона. Они работают в одну сторону - после срабатывания они в конечном итоге закрывают контекст.
Если вы находитесь в среде Linux, все, что вам нужно сделать, это создать символическую ссылку на ваш файл .jar из /etc/init.d/
Затем вы можете запустить приложение, как и любой другой сервис
Таким образом, приложение не будет завершено при выходе из терминала. И приложение будет корректно завершено с командой остановки.
Если вы используете maven, вы можете использовать плагин Maven App .
Демон mojo (который встраивает JSW ) выведет сценарий оболочки с аргументом start/stop. stop будет корректно завершать работу/убивать ваше приложение Spring.
Тот же сценарий можно использовать для использования приложения maven в качестве службы linux.
У них есть много способов закрыть приложение весны. Одним из них является вызов close () для ApplicationContext :
Ваш вопрос предполагает, что вы хотите закрыть свое приложение, выполнив Ctrl+C , который часто используется для завершения команды. В этом случае.
Используйте endpoints.shutdown.enabled=true не лучший рецепт. Это означает, что вы предоставляете конечную точку для завершения вашего приложения. Таким образом, в зависимости от вашего варианта использования и вашей среды, вам придется обеспечить его .
Ctrl+C должен работать очень хорошо в вашем случае. Я предполагаю, что ваша проблема вызвана амперсандом (&). Больше объяснений:
Я не знаю, настроил ли Spring Boot этот хук автоматически, как вы сказали. Я предполагаю, что это так.
Nohup - команда, которая выполняет следующую программу с ловушкой, чтобы игнорировать сигнал HUP. HUP используется для завершения программы, когда вы кладете трубку (например, закрывайте ssh-соединение). Более того, он перенаправляет выходные данные, чтобы ваша программа не блокировалась на пропавшем TTY. Nohup НЕ игнорирует сигнал INT. Так что это не мешает Ctrl+C работать.
Я предполагаю, что ваша проблема вызвана амперсандом (&), а не Nohup. Ctrl+C отправляет сигнал на передний план процессов. Амперсанд заставляет ваше приложение работать в фоновом режиме. Одно из решений: сделать
Использовать kill -9 или kill -KILL плохо, потому что приложение (здесь JVM) не может перехватить его для корректного завершения.
Другое решение - вернуть ваше приложение на передний план. Тогда Ctrl+C будет работать. Взгляните на управление Bash Job, точнее на fg .
Читайте также: