{"id":260,"date":"2024-03-03T20:08:06","date_gmt":"2024-03-03T19:08:06","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=260"},"modified":"2024-03-08T20:25:48","modified_gmt":"2024-03-08T19:25:48","slug":"herunterfahren-von-spring-boot-anwendungen","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=260","title":{"rendered":"Herunterfahren von Spring Boot Anwendungen"},"content":{"rendered":"\n<p>Spring Boot ist ein beliebtes Framework f\u00fcr die Entwicklung von Java-Anwendungen, insbesondere f\u00fcr Microservices. Bei der Entwicklung von Anwendungen ist es wichtig, sicherzustellen, dass sie ordnungsgem\u00e4\u00df heruntergefahren werden, um Datenverlust oder inkonsistente Zust\u00e4nde zu vermeiden. In diesem Artikel werden wir uns darauf konzentrieren, wie man eine Spring Boot-Anwendung sauber herunterf\u00e4hrt und lang laufende Aufgaben mithilfe eines eigenen <code>ThreadPoolTaskExecutor<\/code> ordnungsgem\u00e4\u00df beendet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Hintergrund<\/h2>\n\n\n\n<p>Bevor wir in die Details eingehen, lassen Sie uns einen kurzen Blick darauf werfen, warum ein sauberes Herunterfahren von Anwendungen wichtig ist. Wenn eine Anwendung abrupt gestoppt wird, k\u00f6nnen laufende Aufgaben, Datenbankverbindungen oder andere Ressourcen nicht ordnungsgem\u00e4\u00df freigegeben werden, was zu Datenverlust oder inkonsistenten Zust\u00e4nden f\u00fchren kann. Spring Boot bietet Mechanismen, um sicherzustellen, dass eine Anwendung vor dem Beenden alle notwendigen Schritte durchf\u00fchrt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. ContextClosedEvent f\u00fcr sauberes Herunterfahren<\/h2>\n\n\n\n<p>Spring Boot bietet das <code>ContextClosedEvent<\/code>, das ausgel\u00f6st wird, wenn der Anwendungscontext geschlossen wird. Dieses Event eignet sich gut, um benutzerdefinierte Aktionen vor dem Herunterfahren durchzuf\u00fchren. Hier ist ein Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> org.springframework.boot.SpringApplication;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.boot.autoconfigure.SpringBootApplication;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.ConfigurableApplicationContext;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.event.ContextClosedEvent;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.event.EventListener;\n\n@SpringBootApplication\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyApplication<\/span> <\/span>{\n\n    public <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> main(<span class=\"hljs-built_in\">String<\/span>&#91;] args) {\n        ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args);\n\n        <span class=\"hljs-comment\">\/\/ F\u00fcgen Sie hier Ihren Code f\u00fcr die Anwendung hinzu<\/span>\n\n        SpringApplication.exit(context, () -&gt; <span class=\"hljs-number\">0<\/span>);\n    }\n\n    @EventListener\n    public <span class=\"hljs-keyword\">void<\/span> onContextClosed(ContextClosedEvent event) {\n        <span class=\"hljs-comment\">\/\/ F\u00fcgen Sie hier Ihren eigenen Code f\u00fcr das Herunterfahren hinzu<\/span>\n        System.out.println(<span class=\"hljs-string\">\"Anwendung wird heruntergefahren...\"<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel wird eine Methode mit dem <code>@EventListener<\/code>-Annotation erstellt, die auf das <code>ContextClosedEvent<\/code> reagiert. Der Code, der vor dem Herunterfahren ausgef\u00fchrt werden soll, kann in dieser Methode platziert werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. ThreadPoolTaskExecutor f\u00fcr lang laufende Aufgaben<\/h2>\n\n\n\n<p>Um lang laufende Aufgaben ordnungsgem\u00e4\u00df zu beenden, sollten Sie einen eigenen <code>ThreadPoolTaskExecutor<\/code> konfigurieren. Hier ist eine Beispielkonfiguration in einer Spring Boot-Anwendung:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Bean;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.context.annotation.Configuration;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.core.task.TaskExecutor;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.scheduling.annotation.EnableAsync;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;\n\n@Configuration\n@EnableAsync\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TaskExecutorConfig<\/span> <\/span>{\n\n    @Bean\n    public TaskExecutor taskExecutor() {\n        ThreadPoolTaskExecutor executor = <span class=\"hljs-keyword\">new<\/span> ThreadPoolTaskExecutor();\n        executor.setCorePoolSize(<span class=\"hljs-number\">5<\/span>);\n        executor.setMaxPoolSize(<span class=\"hljs-number\">10<\/span>);\n        executor.setQueueCapacity(<span class=\"hljs-number\">25<\/span>);\n        executor.setThreadNamePrefix(<span class=\"hljs-string\">\"MyTaskExecutor-\"<\/span>);\n        executor.setWaitForTasksToCompleteOnShutdown(<span class=\"hljs-literal\">true<\/span>);\n        executor.setAwaitTerminationSeconds(<span class=\"hljs-number\">60<\/span>);\n        executor.initialize();\n        <span class=\"hljs-keyword\">return<\/span> executor;\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel werden <code>setWaitForTasksToCompleteOnShutdown<\/code> und <code>setAwaitTerminationSeconds<\/code> verwendet, um sicherzustellen, dass laufende Aufgaben vor dem Herunterfahren abgeschlossen werden. Der <code>ThreadPoolTaskExecutor<\/code> wartet bis zu 60 Sekunden, bevor er beendet wird, um laufende Aufgaben abzuschlie\u00dfen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Sauberes Beenden von lang laufenden Aufgaben<\/h2>\n\n\n\n<p>Um sicherzustellen, dass lang laufende Aufgaben sauber beendet werden, m\u00fcssen Sie sicherstellen, dass Sie Ihre Aufgaben so implementieren, dass sie auf Abbruchsignale reagieren k\u00f6nnen. Dies kann durch die Verwendung von <code>Thread.interrupted()<\/code> oder <code>Future.cancel(true)<\/code> erreicht werden. Hier ist ein einfaches Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">import<\/span> org.springframework.scheduling.annotation.Async;\n<span class=\"hljs-keyword\">import<\/span> org.springframework.stereotype.Service;\n\n@Service\npublic <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">MyTaskService<\/span> <\/span>{\n\n    @Async\n    public <span class=\"hljs-keyword\">void<\/span> executeLongRunningTask() {\n        <span class=\"hljs-keyword\">while<\/span> (!Thread.interrupted()) {\n            <span class=\"hljs-comment\">\/\/ F\u00fchren Sie hier Ihre lang laufende Aufgabe aus<\/span>\n            System.out.println(<span class=\"hljs-string\">\"Lang laufende Aufgabe wird ausgef\u00fchrt...\"<\/span>);\n        }\n        System.out.println(<span class=\"hljs-string\">\"Lang laufende Aufgabe wurde abgebrochen.\"<\/span>);\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In diesem Beispiel wird die Aufgabe in einer Schleife ausgef\u00fchrt und \u00fcberpr\u00fcft, ob der Thread unterbrochen wurde. Wenn ja, wird die Aufgabe ordnungsgem\u00e4\u00df beendet. Sie k\u00f6nnen diese Logik entsprechend Ihren Anforderungen anpassen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Zusammenfassung<\/h2>\n\n\n\n<p>Das saubere Herunterfahren von Spring Boot-Anwendungen und das Beenden von lang laufenden Aufgaben erfordert eine sorgf\u00e4ltige Planung und Implementierung. Durch die Verwendung des <code>ContextClosedEvent<\/code> k\u00f6nnen Sie vor dem Herunterfahren der Anwendung benutzerdefinierten Code ausf\u00fchren. Das Konfigurieren eines eigenen <code>ThreadPoolTaskExecutor<\/code> gibt Ihnen mehr Kontrolle \u00fcber die Ausf\u00fchrung und Beendigung von lang laufenden Aufgaben. Stellen Sie sicher, dass Ihre lang laufenden Aufgaben auf Abbruchsignale reagieren, um ein sicheres Herunterfahren zu gew\u00e4hrleisten.<\/p>\n\n\n\n<p>Mit diesen Best Practices k\u00f6nnen Sie sicherstellen, dass Ihre Spring Boot-Anwendung ordnungsgem\u00e4\u00df heruntergefahren wird und lang laufende Aufgaben sicher beendet werden, was zu einer robusten und zuverl\u00e4ssigen Anwendung f\u00fchrt.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Spring Boot ist ein beliebtes Framework f\u00fcr die Entwicklung von Java-Anwendungen, insbesondere f\u00fcr Microservices. Bei der Entwicklung von Anwendungen ist es wichtig, sicherzustellen, dass sie ordnungsgem\u00e4\u00df heruntergefahren werden, um Datenverlust oder inkonsistente Zust\u00e4nde zu vermeiden. In diesem Artikel werden wir uns darauf konzentrieren, wie man eine Spring Boot-Anwendung sauber herunterf\u00e4hrt und lang laufende Aufgaben mithilfe [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-260","post","type-post","status-publish","format-standard","hentry","category-spring"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/260","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=260"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/260\/revisions"}],"predecessor-version":[{"id":261,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/260\/revisions\/261"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=260"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=260"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=260"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}