SPRING JVM Shutdown Hook 的注册与行为分析

dalang · · 120 次点击 · · 开始浏览    
--- ### **1. JVM 的信号处理与 Spring 的联动** #### **(1)JVM 的响应** • **SIGTERM 信号的作用**:`kill -15` 是操作系统通知进程终止的“软终止”信号。JVM 接收到此信号后,会启动 **Shutdown Hook** 机制,依次执行所有注册的关闭钩子(如 Spring 的钩子)。 • **强制终止与优雅终止的区别**:`kill -9`(SIGKILL)会直接终止进程,不触发任何钩子;而 `kill -15` 允许 JVM 执行清理逻辑。 #### **(2)Spring 的注册与触发** • **Spring 的 Shutdown Hook**:Spring 在启动时(通过 `AbstractApplicationContext`)会向 JVM 注册一个 Shutdown Hook。当 JVM 收到 `SIGTERM` 时,该 Hook 会调用 Spring 的 `doClose()` 方法,触发以下操作: 1. 发布 `ContextClosedEvent` 事件,通知监听器容器即将关闭。 2. 销毁所有单例 Bean,依次执行 `@PreDestroy` 方法、`DisposableBean#destroy()` 接口方法、自定义销毁方法(如 `destroy-method`)。 3. 关闭内嵌的 Web 服务器(如 Tomcat),停止接收新请求,并等待已有请求处理完成。 --- ### **2. Spring 优雅关闭的核心流程** #### **(1)Bean 销毁与资源释放** • **`@PreDestroy` 注解**:标记在 Bean 方法上,Spring 会在销毁前调用该方法释放资源(如关闭数据库连接)。 • **`DisposableBean` 接口**:实现该接口的 Bean 需定义 `destroy()` 方法,用于自定义清理逻辑。 • **自定义销毁方法**:通过 XML 或 Java 配置的 `destroy-method` 属性指定。 #### **(2)Web 服务器的优雅停机** • **Tomcat 的关闭逻辑**:Spring 会关闭 Tomcat 的连接器(停止接受新请求),并轮询检查所有活跃请求是否完成。若未完成,则等待至超时(默认 30 秒)后强制终止。 • **配置优化**:在 Spring Boot 2.3+ 中,可通过 `server.shutdown=graceful` 和 `spring.lifecycle.timeout-per-shutdown-phase=30s` 调整等待时间。 #### **(3)微服务场景的扩展** • **注册中心注销**:在 Spring Cloud 中,服务会先从注册中心(如 Nacos、Eureka)下线,避免其他服务继续调用已关闭实例。 • **客户端缓存问题**:即使服务已注销,客户端可能因本地缓存(如 Ribbon 的 30 秒缓存)继续请求旧实例地址,需结合服务发现机制优化等待时间。 --- ### **3. 验证与异常处理** #### **(1)验证流程** • **日志观察**:执行 `kill -15` 后,Spring 会输出以下日志: ```log Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext Unregistering JMX-exposed beans on shutdown ShutdownHook executed ``` • **测试案例**:对比 `kill -15` 与 `kill -9`,前者会触发 Bean 销毁和资源释放,后者直接终止进程且无清理日志。 #### **(2)异常处理** • **超时强制终止**:若关闭阶段超时(如请求未处理完),Spring 会记录警告并终止 JVM。 • **死锁与阻塞**:若 Shutdown Hook 因死锁卡住,需结合运维监控(如 Kubernetes 的 `terminationGracePeriodSeconds`)设置强制终止阈值。 --- ### **4. 最佳实践** 1. **优先使用 `kill -15`**:避免 `kill -9` 导致数据不一致或资源泄漏。 2. **配置超时时间**:根据业务场景调整 `spring.lifecycle.timeout-per-shutdown-phase`,平衡关闭速度与请求完整性。 3. **结合容器化部署**:在 Kubernetes 中配置 `preStop Hook`,先注销服务再等待缓存过期,最后发送 `SIGTERM`。 4. **监控关闭事件**:通过 `ApplicationListener<ContextClosedEvent>` 监听关闭事件,补充自定义清理逻辑。 --- ### **总结** JVM 收到 `kill -15` 信号后,会触发 Spring 的优雅关闭流程,包括 Bean 销毁、资源释放和 Web 服务器停机。这一机制依赖 Spring 注册的 Shutdown Hook 和生命周期管理,确保服务终止时数据安全和系统稳定。
120 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传