Завершение работы приложений Spring Boot

Завершение работы приложений Spring Boot

19 декабря 2022 г.

Последние 3-4 года я работал над Spring Boot и его ассоциациями, такими как Spring Cloud, Spring Data и Spring Security. У меня всегда было искушение использовать комбинацию [Ctrl+C] и [taskkill] для уничтожения приложений или процессов весенней загрузки. Это можно автоматизировать с помощью пакетного сценария, но обычно мне было довольно лень делать это самому, так как комбинация действий служила цели! :-) Почти всегда в командной строке [Ctrl+C] убивает процесс приложения Spring Boot, но в Eclipse (IDE) результат сильно отличается. Процесс переживает завершение приложения весенней загрузки [Ctrl+C] в случае IDE. В любом случае, эти ненадежные и непоследовательные результаты на разных платформах требуют от нас поиска стандартных или чистых способов завершения работы приложений и процессов Spring Boot. Обратите внимание, что эта статья ориентирована на операционную систему Windows.


Ссылка GitHub на репозиторий клонов/разветвленный код

https://github.com/sumithpuri/skp-spring-boot-shutdown


Помните, что в этой статье объясняются способы «чистого» завершения работы приложения Spring Boot. Это означает, что завершение приложения Spring Boot также приведет к немедленному завершению его процесса. Это отличается от постепенного завершения работы на уровне приложения, когда приложению может потребоваться выполнить определенные действия или подождать определенный период времени, чтобы корректно ответить на текущие запросы или завершить текущую обработку.


1. Завершить приложение, завершить процесс (командная строка) — IDE

Самый простой метод, используемый большинством разработчиков. Нажмите кнопку [Завершить — Red Square в Eclipse на вкладке консоли]. Вы заметите, что приложение немедленно закрывается. Но на самом деле в фоновом режиме сервер tomcat все еще работает на порту, с которого он был запущен!

Вы можете проверить этот факт, введя эту команду в командной строке

netstat -ao  

Вы получите один из таких экранов. Найдите порт, на котором вы запустили сервер Tomcat.

Найдите PID и завершите задачу (Windows/MS-DOS)

taskkill /F /PID 14836

Обратите внимание: если вы запускали приложение из командной строки, вы можете просто нажать [Ctrl+C], чтобы закрыть приложение. В большинстве случаев это также убивает процесс. Но если это не убьет процесс, вам следует выполнить вышеуказанные шаги.


[1a] Автоматизировать запись идентификатора процесса в файл

[Вышеупомянутая задача определения идентификатора процесса, связанного с приложением, может быть автоматизирована или запрограммирована с помощью ApplicationPidFileWriter, как показано ниже. В приведенном ниже примере при запуске сервера он запишет PID в имя файла «sbshutdownwin.pid». Позже можно выполнить те же шаги, что и описанные выше, чтобы завершить процесс. Обратите внимание, что шаги также можно автоматизировать с помощью пакетного сценария в Windows/MS-DOS]

 SpringApplication springBootapplication = new SpringApplication(SpringBootDockerApplication.class);  
 springBootapplication.addListeners(new ApplicationPidFileWriter("sbshutdownwin.pid"));  
 springBootapplication.run();  

2. Завершить приложение, завершить процесс (TCPView)

Есть еще один способ немедленно завершить процесс с помощью инструмента TCPView, предоставляемого корпорацией Майкрософт. Он доступен по этой ссылке для загрузки.

Следующий простой способ предложен мной. Начните с нажатия кнопки [Завершить — Red Square в Eclipse на вкладке консоли]. Вы заметите, что приложение немедленно закрывается. Но на самом деле в фоновом режиме сервер tomcat по-прежнему будет работать на порту, с которого он был запущен!

Используйте указанный выше инструмент TCPView, чтобы найти процесс на основе порта, на котором вы запустили приложение Tomcat Server/Spring Boot. Щелкните правой кнопкой мыши элемент процесса/строки и выберите [Убить процесс...], а затем еще раз нажмите [ОК], чтобы подтвердить уничтожение процесса операционной системы.

Это очень удобный способ, особенно если вы архитектор программного обеспечения или инженер, у которого есть много микросервисов для разработки/управления/обслуживания. Это будет полезно, когда вы занимаетесь тестированием/отладкой/исправлением ошибок.


3. Завершение работы с помощью конечной точки актуатора

Самый «чистый» способ из тех, что я описал до сих пор, — это использование Actuator для закрытия приложений весенней загрузки. Вы начнете с того, что включите следующее в свой pom.xml

Затем убедитесь, что вы включили конечную точку выключения через привод, используя свойства, как показано ниже.

Как только вам нужно закрыть приложение, конечная точка привода /shutdown также остановит связанный с ним процесс. Это очень простой способ закрыть приложения Spring Boot. Вы должны убедиться, что вы вызываете конечную точку привода /shutdown только через запрос [POST].

Если Spring Boot является корневым контекстом вашего приложения Spring Boot, вызов будет выглядеть следующим образом. На приведенной выше диаграмме показан ответ на запрос, отправленный через Postman.

http://localhost:8080/springbootdocker/actuator/shutdown  

4. Закройте контекст приложения Spring Boot

Контекст приложения должен сохраняться при запуске/запуске приложения весенней загрузки в классе приложения весенней загрузки.

 public class SpringBootDockerApplication {  
      // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context  
      // Not a Recommended Way to Use public static - Only for the Demo Purposes..  
      public static ConfigurableApplicationContext ctx;  
      public static void main(String[] args) {  
           // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context  
           ctx = SpringApplication.run(SpringBootDockerApplication.class, args);  
      }  
 }  

Затем вы можете использовать следующий метод контроллера для асинхронного закрытия контекста. Также обратите внимание, что для любой очистки был добавлен метод PreDestroy.

      // Starting Threads using Runnable is Not Always the Best Way..  
      // Do Explore Other Integrated Approaches such as Async Servlet  
      @RequestMapping(value = "/shutdown2", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)  
      public ResponseEntity<Object> rule() {  
           System.out.println("Entry Thread Id (Debug): " + Thread.currentThread().getName());  
           Runnable runnable= () -> {  
                try {  
                     Thread.sleep(2000);  
                } catch (InterruptedException e) {  

                     System.out.println("Thread was Interrupted! Error in Thread Sleep (2 Seconds!)");  
                }  
                System.out.println("Callable Thread Id: " + Thread.currentThread().getName());  
                SpringBootDockerApplication.ctx.close();            
           };  

           new Thread(runnable).start();  
           System.out.println("Exit Thread Id (Debug): " + Thread.currentThread().getName());  
           return new ResponseEntity<>("Shutdown Requested - Will Shutdown in Next 2 Seconds!", HttpStatus.OK);  
      }  



      @PreDestroy  
      public void requestShutdown2PreDestroy() {  

           System.out.println("Requested Shutdown (via Context) of the Spring Boot Container");  
      }  

После того, как вышеописанное было сделано, построено и развернуто. Затем вы можете закрыть весеннюю загрузку, используя следующий запрос браузера.

Вы заметите, что приложение было закрыто, когда увидите консоль, а также процесс был удален из процессов операционной системы.


5. Выйдите с помощью SpringApplication.exit()

Другой способ — использовать метод exit() класса SpringApplication, для завершения процесса также потребуется использовать System.exit()

    // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context   
    // Not a Recommended Way to Use public static - Only for the Demo Purposes..   
    private static ConfigurableApplicationContext ctx;   

    public static void main(String[] args) {   

       // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context   
       ctx = SpringApplication.run(SpringBootDockerApplication.class, args);   
    }   

    public static void exitApplication() {   
       int staticExitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {   

        @Override   
        public int getExitCode() {   
        // no errors   
        return 0;   
        }   
       });   

       System.exit(staticExitCode );   
    }   

n Контроллер будет выглядеть так, как мы написали ранее. После того, как ваше приложение запущено и вы хотите завершить работу приложения «чисто», вы можете использовать следующее:

Вы заметите, что приложение было закрыто, когда увидите консоль, а также процесс был удален из процессов операционной системы.


Остерегайтесь следующей статьи из этой серии под названием «SKP’s SB #03: Spring Boot Annotation Reference-01/a». «Серия статей SKP SB» полностью основана на Spring Boot, а также на связанных темах, таких как Docker Desktop, таймеры Java, аннотации Spring и чистое завершение работы приложений Spring Boot.

:::информация Также опубликовано здесь.

:::


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE