首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >优雅上下线:滚动发布的连接排空与预热

优雅上下线:滚动发布的连接排空与预热

原创
作者头像
PikeTalk
发布于 2026-11-03 19:40:53
发布于 2026-11-03 19:40:53
1400
举报

优雅上下线:滚动发布的连接排空与预热

滚动发布的目标听起来简单:新版本逐个替换旧版本,全程不中断服务。但实现里藏着两个经典坑:下线时在途请求被掐断(用户看到 502),上线时缓存全空(首批请求全打到数据库)。优雅上下线就是解这两个坑的工程化方案——一个是排空(drain),一个是预热(warmup)。

一、下线排空:三段式的完整流程

一个实例从「接流量」到「安全退出」要走三步,缺一步都有故障现场:

第一段:注册中心摘除。实例先从注册中心(Nacos/Consul/K8s Service)反注册。这一步之后,新的请求不再路由到它——但已经建立的健康检查、已发布的客户端本地缓存还没过期,摘除通知传播需要几秒。摘除后必须等待,等多久取决于客户端缓存刷新周期(常见 5~30 秒)。

第二段:网关侧摘除。注册中心之外,负载均衡层(LB/网关)往往有自己的健康检查周期。主动把 LB 的健康检查置为失败(返回 503)或调用 LB 的摘除接口,让 LB 层立刻摘掉它——不等自然健康检查超时。

第三段:等待在途请求完成。摘除只挡新流量,在途的怎么办?等待一个「排空窗口」:sleep 一个大于请求最长处理时间的值(通常取 P999 的 3~5 倍,比如 30 秒),让在途请求自然做完再退出。K8s 里的标准实现是 preStop hook 里 sleep 30,配 terminationGracePeriodSeconds 覆盖。

三段合起来的 K8s 标准配置:preStop 先调摘除接口(或靠 termination 端点自己摘注册),然后 sleep 排空窗口,最后进程退出。

二、长连接的排空:难一个量级

HTTP/1.1 短连接的排空靠「等」就行,长连接(WebSocket/gRPC)不行——连接不会自然结束,「等 30 秒」等不到任何东西,客户端会一直挂在这个实例上直到天荒地老。

长连接的排空要主动驱赶:a. 服务端发 Close 帧(WebSocket 的 close frame / gRPC 的 GOAWAY)通知客户端「我要下了,请重连」;b. 客户端收到 Close 后按重连策略连到别的实例(重连时从注册中心拿最新列表);c. 服务端在 Close 后再等一个窗口(比如 60 秒)处理完在途消息再断 TCP。

没有 a+b 的配合,长连接实例下线就是硬切——客户端突然收到 TCP RST,正在写的消息丢失。所以长连接服务的发布必须实现 GOAWAY 协议,且客户端的重连逻辑要处理「收到 Close 立即重连」。这是很多团队第一次做长连接滚动发布时踩的坑:服务端发了 Close,但客户端没实现重连(或者重连没加退避),发布变成连接风暴。

三、上线预热:别让第一批请求裸奔

新实例启动后立刻接全量流量,会经历一个「冷启动恶化期」:JIT 未编译(Java 前几千个请求慢 3~5 倍)、本地缓存全空(缓存穿透打到 DB)、连接池未建立(首批请求排队建连接)。高峰发布时,这个恶化期足以引发 DB 过载——所以预热是发布工程的标配。

预热的三种手段:

流量爬坡:新实例上线时网关权重从 1% 起步,按 1% → 5% → 25% → 100% 的阶梯爬升,每级观察 1~2 分钟。最通用的方案,不依赖应用改造,网关支持就行。

预热请求回放:新实例启动后,先自我加压——用压测流量或录制回放真实请求打自己(QPS 从低到高爬),等 JIT 编译完、缓存填热后再挂到 LB。对 Java 类 JIT 敏感的应用效果显著。

缓存预加载:启动时主动把关键数据加载进本地缓存(从 Redis 拉全量配置、从 DB 拉热点数据),避免线上流量承担冷缓存成本。

生产组合是 a + b/c:流量爬坡保底,预热回放/预加载对性能敏感的服务加配。

四、把整个流程做成自动化的检查清单

手动发布永远会漏步骤——优雅上下线的正确形态是平台化:

发布系统的每一步做成自动检查:摘除后轮询注册中心确认已摘干净(列表里没有该实例)→ 排空窗口计时 → 新版本就绪检查(health endpoint 返回 ready 而不只是 alive)→ 权重爬坡 → 全量。检查不过自动暂停发布并告警,而不是继续滚。

ready 与 alive 的区分是预热的接口基础:alive 表示进程活着,ready 表示「缓存已热、依赖已连、可以接流量」。K8s 的 readinessProbe 探的是 ready——新实例没 ready 之前不会被挂到 Service 后端,这就是平台层的爬坡保障。

回滚也要优雅:回滚是反向的滚动发布,同样需要排空和预热。快速回滚(--record 的版本切换)经常被实现为「硬杀旧起新」,这是发布事故的常见来源——回滚救火时把「优雅」忘了。

五、验收标准:发布过程用户无感

怎么知道优雅上下线做对了?三个验收指标:1. 发布期间 5xx 率零上升(在途请求被掐断会表现为 502);2. 发布期间 DB QPS 无毛刺(冷缓存穿透表现为 DB 查询量尖峰);3. 长连接服务的重连率曲线(发布窗口内重连次数 = 被下线的连接数,无 RST 尖峰)。这三个指标接进发布流水线的卡点,每次发布自动验证——优雅上下线就从「最佳实践」变成了「不可回退的工程事实」。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

目录
  • 优雅上下线:滚动发布的连接排空与预热
    • 一、下线排空:三段式的完整流程
    • 二、长连接的排空:难一个量级
    • 三、上线预热:别让第一批请求裸奔
    • 四、把整个流程做成自动化的检查清单
    • 五、验收标准:发布过程用户无感
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档