首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >线上服务如何优雅停机?

线上服务如何优雅停机?

作者头像
苏三说技术
发布2025-07-29 09:11:34
发布2025-07-29 09:11:34
18700
代码可运行
举报
文章被收录于专栏:苏三说技术苏三说技术
运行总次数:0
代码可运行

大家好,我是苏三,又跟大家见面了。

前言

最近星球中有位小伙伴问了我一个问题:如何优雅的停机?

我觉得这个问题挺有代表性的。

今天这篇文章跟大家一下优雅停机的一些常见方案,希望对你会有所帮助。

1.什么是优雅停机?

优雅停机(Graceful Shutdown) 指在服务终止前,系统能:

  1. 拒绝新请求进入
  2. 完成存量请求处理
  3. 释放所有资源
  4. 通知上下游服务

非优雅停机的惨痛代价

真实案例:支付回调丢失。

代码语言:javascript
代码运行次数:0
运行
复制
// 支付回调处理
@PostMapping("/callback")
public void handleCallback(Payment payment) {
    // 1. 更新订单状态
    orderService.updateStatus(payment.getOrderId(), PAID);
    
    // 2. 发放权益(kill发生时此处未执行)
    benefitService.grantVip(payment.getUserId()); 
}

当kill发生在步骤1和2之间时,导致订单状态已更新但权益未发放,引发用户投诉。

2.优雅停机三大核心流程

2.1 信号捕获层

2.2 流量控制层

2.3 资源释放层

3.Spring Boot优雅停机的实现

3.1 基础配置

在SpringBoot项目的application.yml文件中增加如下配置:

代码语言:javascript
代码运行次数:0
运行
复制
server:
  shutdown: graceful # 开启优雅停机
  
spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s # 最长等待时间

3.2 线程池优雅关闭

在线程池中实现优雅关闭功能:

代码语言:javascript
代码运行次数:0
运行
复制
@Bean
public ExecutorService threadPool() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setWaitForTasksToCompleteOnShutdown(true); // 等待任务完成
    executor.setAwaitTerminationSeconds(60); // 最大等待时间
    return executor.getThreadPoolExecutor();
}

在shutdown之前,先等待任务完成。

3.3 分布式锁释放拦截器

代码语言:javascript
代码运行次数:0
运行
复制
@Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
public Object handleRequest(ProceedingJoinPoint pjp) {
    Lock lock = redisson.getLock("order_lock");
    try {
        lock.lock();
        return pjp.proceed();
    } finally {
        if (!isShuttingDown()) {
            lock.unlock(); // 非停机时正常释放
        }
        // 停机时由锁管理器统一释放
    }
}

使用统一的拦截器释放分布式锁,防止出现异常有释放遗漏的地方。

4.Kubernetes环境下的优雅停机

4.1 关键配置

代码语言:javascript
代码运行次数:0
运行
复制
STOPSIGNAL SIGTERM # 使用SIGTERM替代SIGKILL
代码语言:javascript
代码运行次数:0
运行
复制
# Deployment配置
spec:
terminationGracePeriodSeconds:60# 宽限期
containers:
    -lifecycle:
        preStop:
          exec:
            command:["/bin/sh","-c","sleep 20;"]# 预留缓冲时间

在部署配置中增加预留缓冲时间。

4.2 就绪探针自动摘流

5.中间件连接优雅关闭

5.1 数据库连接池

代码语言:javascript
代码运行次数:0
运行
复制
@PreDestroy
public void close() {
    HikariPool pool = dataSource.getHikariPoolMXBean();
    pool.suspendPool(); // 停止借出连接
    pool.softEvictConnections(); // 驱逐空闲连接
    while (pool.getActiveConnections() > 0) {
        Thread.sleep(500); // 等待活动连接完成
    }
    pool.shutdown(); // 彻底关闭
}

使用@PreDestroy在服务销毁之前关闭数据库连接池。

5.2 RabbitMQ消费者

代码语言:javascript
代码运行次数:0
运行
复制
@PreDestroy
public void stop() {
    channel.basicCancel(consumerTag); // 取消订阅
    while (unackedMessages.get() > 0) {
        Thread.sleep(100); // 等待ACK完成
    }
    connection.close();
}

@PreDestroy在服务销毁之前取消订阅,需要先等待ACK完成。

3. Redis分布式锁
代码语言:javascript
代码运行次数:0
运行
复制
public class LockManager implements DisposableBean {
    @Override
    public void destroy() {
        lockMap.forEach((key, lock) -> {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock(); // 强制释放未解锁的锁
            }
        });
    }
}

实现DisposableBean接口,在服务销毁之前强制释放未解锁的锁。

6.全链路优雅停机

6.1 停机事件传播机制

6.2 状态机管理

代码语言:javascript
代码运行次数:0
运行
复制
public enum ShutdownState {
    RUNNING,    // 正常运行
    PRE_SHUTDOWN, // 拒绝新请求
    DRAINING,    // 排空存量请求
    TERMINATED   // 完全终止
}

6.3 停机监控面板

7.生产环境避坑指南

7.1 必须避免的四大陷阱

陷阱

后果

解决方案

死锁等待

无法完成停机

设置锁超时时间

第三方服务不可用

资源无法释放

添加熔断机制

长周期任务

超过宽限期被强杀

拆分任务+保存中间状态

文件写入未完成

数据损坏

使用原子文件替换

7.2 停机检查清单

代码语言:javascript
代码运行次数:0
运行
复制
# 停机前执行
curl -X POST http://localhost:8080/actuator/shutdown-prepare

# 验证项:
1. 新请求返回503
2. 活动线程数持续下降
3. 数据库连接数归零
4. MQ无未ACK消息

7.3 黄金法则:二段式停机

总结

  1. 基础层:处理HTTP请求 Spring Boot Graceful Shutdown + 线程池等待
  2. 进阶层:管理中间件连接 数据库连接池排空 + MQ消费者取消订阅
  3. 高级层:分布式协同 停机事件广播 + 分布式锁释放
  4. 终极层:全链路状态管理 停机状态机 + 智能超时控制

停机策略对比表

策略

实现难度

停机时间

数据安全

适用场景

直接kill -9

秒级

极低

开发环境

Spring Boot

☆☆

10-30s

常规Web应用

容器化方案

☆☆☆

可配置

K8S环境

全链路管理

☆☆☆☆

分钟级

极高

金融核心系统

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 苏三说技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 大家好,我是苏三,又跟大家见面了。
  • 前言
  • 1.什么是优雅停机?
  • 2.优雅停机三大核心流程
    • 2.1 信号捕获层
    • 2.2 流量控制层
    • 2.3 资源释放层
  • 3.Spring Boot优雅停机的实现
    • 3.1 基础配置
    • 3.2 线程池优雅关闭
    • 3.3 分布式锁释放拦截器
  • 4.Kubernetes环境下的优雅停机
    • 4.1 关键配置
    • 4.2 就绪探针自动摘流
  • 5.中间件连接优雅关闭
    • 5.1 数据库连接池
    • 5.2 RabbitMQ消费者
      • 3. Redis分布式锁
  • 6.全链路优雅停机
    • 6.1 停机事件传播机制
    • 6.2 状态机管理
    • 6.3 停机监控面板
  • 7.生产环境避坑指南
    • 7.1 必须避免的四大陷阱
    • 7.2 停机检查清单
    • 7.3 黄金法则:二段式停机
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档