想象一下,你正在乘坐一辆出租车,突然司机说:“车到一半我得下班了,您赶紧下车吧!”这样的经历肯定会让人感到非常糟糕。这不仅会导致用户体验极差,还可能让出租车平台的订单状态变得混乱——明明行程还在,却被迫中断,最终产生“脏数据”。
在微服务应用中,这种情况的对应场景便是应用程序的突然关闭。无论是因为维护需要还是意外问题,都可能导致用户请求中断,数据未能及时处理。为了解决这个问题,优雅停机机制成为现代系统中的重要一环。
定义: 优雅停机是指在应用停止时,确保以下几点:
目标: 优雅停机的核心是提供一种“无感知”的下线体验,让用户和系统都能安全退出。
从 Spring Boot 2.3 开始,优雅停机的支持更加简单和强大。通过设置 server.shutdown
配置,可以决定应用停机时的行为。
在立即停机模式下,应用会立刻中断所有请求和任务。
server:
shutdown: immediate
虽然简单高效,但这种方式通常只适用于测试或无状态服务。
在优雅停机模式下,Spring Boot 会等待当前的处理任务完成,再进行停机操作。
server:
shutdown: graceful
注意: 该模式下的默认等待时间为 30 秒,可通过
spring.lifecycle.timeout-per-shutdown-phase
进行配置。
Spring Boot 默认会通过 JVM 的 Shutdown Hook 触发优雅停机。确保以下配置启用:
spring:
main:
register-shutdown-hook: true
如果需要在停机时执行特定的清理操作,比如关闭数据库连接或停止线程池,可以通过添加 Shutdown Hook 或实现 DisposableBean
接口。
示例代码:
@Component
public class GracefulShutdownTask implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("关闭数据库连接...");
System.out.println("释放线程池...");
// 其他清理操作
}
}
或者直接通过 JVM 钩子实现:
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("执行自定义的资源清理逻辑");
}));
避免因某些请求耗时过长导致系统停机过程被阻塞,可以通过以下配置设置超时时间:
spring:
lifecycle:
timeout-per-shutdown-phase: 20s # 默认30秒
在系统版本升级时,通过优雅停机完成请求处理和资源释放,避免对用户造成干扰。
在高并发场景下,如果需要暂时下线部分服务节点,优雅停机可以帮助实现“无感”迁移。
如出租车平台,在订单完成后再下线服务,避免出现“中途被抛弃”的情况。
kill -9
强制终止进程将导致优雅停机机制无法触发。在高可用系统中,优雅停机通常需要配合流量控制机制实现。例如:
优雅停机是一项提高用户体验和系统稳定性的关键机制。它通过拒绝新请求、完成当前任务、清理资源等方式,让应用的下线过程更安全、更友好。
通过 Spring Boot 提供的简单配置和扩展接口,我们可以轻松实现优雅停机,同时结合流量控制机制进一步优化用户体验。
推荐实践:
参考
【Spring Boot】【优雅停机一】Spring Boot 停机的正确方式 - 酷酷- - 博客园 (cnblogs.com)
【Spring Boot】【优雅停机二】Spring Boot 停机的正确方式 - 酷酷- - 博客园 (cnblogs.com)