SpringBoot优雅退出 - 编程一生

SpringBoot优雅退出 - 编程一生

💡 原文中文,约2700字,阅读约需7分钟。
📝

内容提要

Spring Boot 默认在 SpringApplication 初始化时设置 registerShutdownHook=true,通过 Runtime 注册 JVM 关闭钩子。收到 SIGTERM(如 kill -15)时,先执行 doClose() 关闭上下文再终止进程;强制退出时该机制无效。退出过程中会关闭 Netty 服务器、Spring 上下文,停止调度任务,并释放 ZooKeeper 与线程池资源。

🔎

延伸解读

优雅退出的触发条件与局限

文章指出,Spring Boot 的优雅退出依赖 JVM 的 shutdown hook 机制,仅在收到 SIGTERM(如 kill -15)时生效。若进程被强制终止(如 kill -9),钩子不会执行,资源无法按预期释放。因此,生产环境应优先使用 SIGTERM 触发关闭,避免强制杀进程导致 Netty、ZooKeeper 等资源未清理。

退出时的资源释放顺序

从日志可见,优雅退出会依次关闭 Netty 服务器、Spring 上下文,并停止调度任务,最后释放 ZooKeeper 与线程池。这种顺序有助于先停止接收新请求,再清理内部状态。读者可据此检查自身应用的关闭逻辑是否覆盖关键资源,避免遗漏。

注册钩子的源码入口

SpringApplication 初始化时默认设置 registerShutdownHook=true,并通过 Runtime.getRuntime().addShutdownHook 注册一个线程,在 JVM 关闭时调用 doClose() 关闭上下文。理解这一入口有助于排查为何某些关闭操作未执行,例如钩子未注册或已被提前关闭。

❓

Q&A

Spring Boot 的优雅退出机制是怎么实现的?

Spring Boot 在 SpringApplication 初始化时默认设置 registerShutdownHook=true,通过 Runtime.getRuntime().addShutdownHook() 注册一个 JVM 关闭钩子。当 JVM 收到 SIGTERM 信号(如 kill -15)时,会先执行钩子中的 doClose() 方法关闭 Spring 上下文,然后再终止进程。

Spring Boot 优雅退出时具体会执行哪些操作?

根据日志,优雅退出时会依次关闭 Netty 服务器(如 NettyHttpServer 和 NettyServer)、关闭 Spring 上下文(AnnotationConfigApplicationContext),停止调度任务(ScheduleManager 检查执行中的任务并回调结果),并释放 ZooKeeper 和线程池等资源。

kill -15 和强制退出在 Spring Boot 优雅退出中有什么区别?

kill -15 发送 SIGTERM 信号,会触发注册的 shutdown hook,执行优雅退出逻辑(如关闭上下文、释放资源)后再终止进程;而强制退出(如 kill -9)不会触发 shutdown hook,优雅退出机制无效。

如何启用或禁用 Spring Boot 的优雅退出?

Spring Boot 默认启用优雅退出(registerShutdownHook=true)。可以通过设置 SpringApplication.setRegisterShutdownHook(false) 来禁用。

Spring Boot 优雅退出时,Netty 服务器是如何关闭的?

优雅退出时,NettyHttpServer 会关闭绑定的端口(如 5080),NettyServer 会停止服务并可能休眠一段时间(如 6 秒)以确保正在处理的请求完成。

Spring Boot 优雅退出时,调度任务和资源是如何处理的?

ScheduleManager 会在退出前检查正在执行的任务并回调结果,然后销毁任务节点资源,包括 ZooKeeper 和线程池。

🏷️

标签

➡️

继续阅读