线上服务如何优雅停机?

向量数据库大模型关系型数据库

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

前言

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

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

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

最近建了一些工作内推群,各大城市都有,欢迎各位HR和找工作的小伙伴进群交流,群里目前已经收集了不少的工作内推岗位。

扫码加苏三的微信:li_su223,备注:所在城市,即可进群。

picture.image

1.什么是优雅停机?

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

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

非优雅停机的惨痛代价

picture.image

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

  
// 支付回调处理  
@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 信号捕获层

picture.image

2.2 流量控制层

picture.image

2.3 资源释放层

picture.image

3.Spring Boot优雅停机的实现

3.1 基础配置

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

  
server:  
  shutdown: graceful # 开启优雅停机  
    
spring:  
  lifecycle:  
    timeout-per-shutdown-phase: 30s # 最长等待时间  

3.2 线程池优雅关闭

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

  
@Bean  
public ExecutorService threadPool() {  
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();  
    executor.setWaitForTasksToCompleteOnShutdown(true); // 等待任务完成  
    executor.setAwaitTerminationSeconds(60); // 最大等待时间  
    return executor.getThreadPoolExecutor();  
}  

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

3.3 分布式锁释放拦截器

  
@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 关键配置

  
STOPSIGNAL SIGTERM # 使用SIGTERM替代SIGKILL  

  
# Deployment配置  
spec:  
terminationGracePeriodSeconds:60# 宽限期  
containers:  
    -lifecycle:  
        preStop:  
          exec:  
            command:["/bin/sh","-c","sleep 20;"]# 预留缓冲时间  

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

4.2 就绪探针自动摘流

picture.image

5.中间件连接优雅关闭

5.1 数据库连接池

  
@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消费者

  
@PreDestroy  
public void stop() {  
    channel.basicCancel(consumerTag); // 取消订阅  
    while (unackedMessages.get() > 0) {  
        Thread.sleep(100); // 等待ACK完成  
    }  
    connection.close();  
}  

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

3. Redis分布式锁

  
public class LockManager implements DisposableBean {  
    @Override  
    public void destroy() {  
        lockMap.forEach((key, lock) -> {  
            if (lock.isHeldByCurrentThread()) {  
                lock.unlock(); // 强制释放未解锁的锁  
            }  
        });  
    }  
}  

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

6.全链路优雅停机

6.1 停机事件传播机制

picture.image

6.2 状态机管理

  
public enum ShutdownState {  
    RUNNING,    // 正常运行  
    PRE\_SHUTDOWN, // 拒绝新请求  
    DRAINING,    // 排空存量请求  
    TERMINATED   // 完全终止  
}  

6.3 停机监控面板

picture.image

7.生产环境避坑指南

7.1 必须避免的四大陷阱

| 陷阱 | 后果 | 解决方案 | | --- | --- | --- | | 死锁等待 | 无法完成停机 | 设置锁超时时间 | | 第三方服务不可用 | 资源无法释放 | 添加熔断机制 | | 长周期任务 | 超过宽限期被强杀 | 拆分任务+保存中间状态 | | 文件写入未完成 | 数据损坏 | 使用原子文件替换 |

7.2 停机检查清单

  
# 停机前执行  
curl -X POST http://localhost:8080/actuator/shutdown-prepare  
  
# 验证项:  
1. 新请求返回503  
2. 活动线程数持续下降  
3. 数据库连接数归零  
4. MQ无未ACK消息  

7.3 黄金法则:二段式停机

picture.image

总结

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

停机策略对比表

| 策略 | 实现难度 | 停机时间 | 数据安全 | 适用场景 | | --- | --- | --- | --- | --- | | 直接kill -9 | ☆ | 秒级 | 极低 | 开发环境 | | Spring Boot | ☆☆ | 10-30s | 中 | 常规Web应用 | | 容器化方案 | ☆☆☆ | 可配置 | 高 | K8S环境 | | 全链路管理 | ☆☆☆☆ | 分钟级 | 极高 | 金融核心系统 |

最后欢迎加入苏三的星球,你将获得:100万QPS短链系统、复杂的商城微服务系统、苏三AI项目、刷题吧小程序、秒杀系统、商城系统、秒杀系统、代码生成工具等8个项目的源代码、开发教程和技术答疑。

系统设计、性能优化、技术选型、底层原理、Spring源码解读、工作经验分享、痛点问题、面试八股文等多个优质专栏。

还有1V1免费修改简历、技术答疑、职业规划、送书活动、技术交流。

目前星球已经更新了5800+篇优质内容,还在持续爆肝中.....

星球已经被官方推荐了3次,收到了小伙伴们的一致好评。戳我加入学习,已有1800+小伙伴加入学习。

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
vivo 容器化平台架构与核心能力建设实践
为了实现规模化降本提效的目标,vivo 确定了基于云原生理念构建容器化生态的目标。在容器化生态发展过程中,平台架构不断演进,并针对业务的痛点和诉求,持续完善容器化能力矩阵。本次演讲将会介绍 vivo 容器化平台及主要子系统的架构设计,并分享重点建设的容器化核心能力。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论