Spring boot 应用程序优雅地捕获 SIGTERM 信号并调用 predestroy 方法

Dev*_*per 4 spring spring-boot

我有一个 Spring Boot 应用程序,当我们使用 kill pid 终止进程时,它需要清除或清理资源。@predestroy 带注释的方法不起作用,也没有被调用。请建议我们如何捕获 SIGTERM 并调用 predestroy 方法

MyT*_*nts 7

理想情况下,它应该可以工作,但要确保SIGTERM被调用而不是SIGKILL

我有几个运行 spring boot 应用程序的情况

码头工人

当你执行docker stop幕后发生的事情是

停止一个或多个正在运行的容器容器内的主进程会收到SIGTERM,经过一个宽限期后,SIGKILL

kill 9955 => SIGTERM 被调用 kill -9 9955=> SIGKILL 被调用

有关杀死的更多详细信息,请参阅此处

现在回到 @PreDestroy

我在 SpringBoot 应用程序中添加了以下行

@PreDestroy
public void tearDown() {
    System.out.println("Shutting Down...............the ");
}
Run Code Online (Sandbox Code Playgroud)

当我这样做时,我得到以下输出 kill portno

2019-01-04 10:52:44.776  INFO o.s.s.c.ThreadPoolTaskScheduler / shutdown - 208 : Shutting down ExecutorService 'taskScheduler'
2019-01-04 10:52:44.783  INFO o.s.s.c.ThreadPoolTaskExecutor / shutdown - 208 : Shutting down ExecutorService 'applicationTaskExecutor'
2019-01-04 10:52:44.785  INFO o.s.o.j.LocalContainerEntityManagerFactoryBean / destroy - 597 : Closing JPA EntityManagerFactory for persistence unit 'default'
2019-01-04 10:52:44.792  INFO c.z.h.HikariDataSource / close - 350 : HikariPool-1 - Shutdown initiated...
2019-01-04 10:52:44.800  INFO c.z.h.HikariDataSource / close - 352 : HikariPool-1 - Shutdown completed.
Shutting Down...............
Run Code Online (Sandbox Code Playgroud)

正如您在日志中看到的,我有 2 个正在运行的调度程序任务和 JPA 实体管理器。收到SIGTERM它首先关闭所有,最后调用 preDestory。

我不确定您还需要做哪些清理工作,但请确保它是否已经清理完毕。

优雅地关闭嵌入式 servlet 容器

您还可以自定义并优雅地编写自己的关闭钩子。 参考这个很好的讨论和示例代码

重构嵌入式 Web 服务器包

请注意上面链接中的示例代码。如果您使用较新版本的 Springboot 更改包可能会丢失。

有关更改的方法和类的更多详细信息,请参阅此处


Paw*_*elS 5

只是对 @MyTwoCents 答案@PreDestroyDocker 的一个小补充-> 确保使用ENTRYPOINT而不是CMDor RUN- 只有这样你才会将应用程序作为主进程运行,并且 SIGTERM 将被发送到你的应用程序