Spring Boot应用实现优雅停服的关键在于确保在服务关闭之前能够完成以下几点:
- 处理完所有已接收的请求:确保正在处理的请求能够正常完成,避免数据丢失或不一致。
- 拒绝新的请求:一旦开始关闭流程,应该立即停止接收新的外部请求。
- 清理资源:释放外部资源,如数据库连接、文件句柄、网络连接等。
- 执行特定的清理操作:如关闭线程池、关闭消息队列消费者等。
使用Spring Actuator的Shutdown端点
-
启用Actuator :在
pom.xml
中添加Spring Boot Actuator依赖。 -
暴露Shutdown端点 :在
application.properties
或application.yml
中配置。1management:
2 endpoints:
3 web:
4 exposure:
5 include: shutdown
6 endpoint:
7 shutdown:
8 enabled: true -
发送关闭请求 :通过发送POST请求到
/actuator/shutdown
来触发优雅停机。
添加自定义的Shutdown Hook
-
在应用启动时,注册一个JVM的Shutdown Hook,用于执行清理工作。
1Runtime.getRuntime().addShutdownHook(new Thread(() -> {
2 // 清理资源、关闭连接等操作
3 System.out.println("执行关闭前的清理工作...");
4}));
利用Spring的Lifecycle Callbacks
-
实现
SmartLifecycle
接口,可以在应用启动和关闭时执行特定逻辑。1@Component
2public class GracefulShutdownCallback implements SmartLifecycle {
3 private volatile boolean isRunning = false;
4
5 @Override
6 public void start() {
7 isRunning = true;
8 // 启动时的操作
9 }
10
11 @Override
12 public void stop() {
13 isRunning = false;
14 // 停止时的清理操作
15 }
16
17 // 其他需要实现的方法...
18}
设置合理的超时时间
- 通过配置
spring.lifecycle.timeout-per-shutdown-phase
来设定每个关闭阶段的超时时间,确保应用有足够的时间来完成清理工作。
异步任务管理
- 如果应用中使用了异步处理,确保在应用关闭时能够正确取消或等待所有异步任务完成。可以使用
AsyncConfigurer
接口来配置。
数据库和消息队列的事务处理
- 确保数据库操作和消息队列的消费能够在接收到关闭信号时正确回滚或提交事务,避免数据不一致性。
确保外部服务调用的幂等性
- 对外调用时,确保操作是幂等的,这样即使在停机过程中重试也不会产生副作用。
监控与日志
- 在执行关闭操作时,记录详细的日志,包括开始关闭、关键资源释放过程和最终状态,以便于排查问题。