旧服务下线方案
旧服务下线技术方案
一、方案目标与原则
核心目标
- 安全停止旧服务,确保业务无感知、数据无丢失
- 彻底回收旧服务占用的资源(服务器、数据库、缓存、域名等)
- 沉淀可复用的服务下线流程,降低后续操作风险
实施原则
- 业务优先:任何操作不得影响核心业务连续性,优先保障用户体验
- 数据驱动:基于监控数据确认服务已无实际流量后再执行下线
- 渐进式执行:从"流量切走→功能冻结→资源回收"分阶段推进,避免一步到位
- 全链路协同:联动依赖方(调用方、运维、业务)同步操作,确保信息对称
二、下线前准备(T-30天至T-7天)
1. 服务信息梳理
需全面摸清旧服务的"家底",避免遗漏关键依赖:
- 基础信息:服务名称、部署架构(单机/集群)、部署环境(生产/测试)、负责人
- 接口信息:所有对外提供的接口(HTTP/gRPC/消息队列)、协议类型、调用量峰值/均值
- 依赖关系:
- 上游调用方:通过网关日志、服务注册中心、链路追踪系统(如Jaeger/Zipkin)梳理所有调用来源(含定时任务、第三方系统)
- 下游依赖:数据库(表名、读写比例)、缓存(Redis键前缀)、消息队列(topic)、其他服务接口
- 数据存储:数据存储位置(DB/ES/对象存储)、数据生命周期(是否需归档)、备份策略
2. 影响范围评估
- 业务影响:明确依赖旧服务的业务场景(核心/非核心)、用户群体(C端/B端)、影响等级(P0-P3)
- 技术影响:评估下线后可能的风险点(如调用方未切换导致的502错误、数据链路中断导致的统计异常)
- 合规影响:若涉及用户数据,需确认是否符合数据留存法规(如金融数据需留存5年),避免违规删除
3. 替代方案确认
- 若旧服务功能已被新服务替代:
- 验证新服务是否100%覆盖旧服务功能(含边缘场景)
- 确认新服务性能(响应时间、吞吐量)、稳定性(错误率、可用性)达标
- 完成调用方从旧服务到新服务的切换方案(如域名切换、配置中心动态路由)
- 若旧服务功能被废弃:
- 确认业务方已同意停止该功能,且无用户依赖
- 清理依赖该功能的前端页面、API文档等
4. 相关方同步与确认
需拉通所有关联角色,达成一致后再推进:
- 业务方:确认下线时间窗口、功能替代方案、用户通知方式(如需)
- 调用方团队:同步下线计划,明确调用方切换截止时间
- 运维团队:确认资源回收清单、备份策略、回滚方案
- 管理层:重大服务下线需获得业务/技术负责人审批
三、灰度下线阶段(T-7天至T-1天)
1. 流量逐步切换
通过"限流→拦截→禁写"三步控制流量,确保调用方平滑迁移:
-
第一步:限流(T-7天)
在网关层或服务入口设置限流规则,逐步降低旧服务的最大QPS(如每天降低20%),倒逼调用方加速切换。
示例(Nginx限流配置):limit_req zone=old_service burst=100 nodelay; # 每天调整burst值,逐步降低
-
第二步:流量拦截(T-3天)
对仍在调用旧服务的请求返回"服务下线通知"(如HTTP 410 Gone),并在响应头中携带新服务地址(X-New-Service-Url
)。
同时通过日志监控剩余调用方,主动推动其切换(如邮件/群通知)。 -
第三步:禁写操作(T-1天)
关闭旧服务的写接口(如数据库写入、缓存更新),仅保留读接口(避免新数据写入后无法同步到新服务),确保数据一致性。
2. 监控与验证
需建立实时监控看板,确认流量逐步归零:
- 核心指标:
- 接口调用量(目标:连续24小时为0)
- 错误率(目标:无新增错误,排除已拦截的410请求)
- 下游依赖调用量(如DB查询、Redis操作,需同步归零)
- 特殊场景验证:
- 定时任务:检查是否有周期性调用(如每日凌晨的批处理),需联系负责人停用
- 第三方系统:确认外部合作方已切换到新服务(可能需商务协调)
四、正式下线执行(T日)
1. 服务停止
按"先非核心环境,后生产环境"的顺序停止服务:
- 测试/预发环境:直接停止进程,删除容器/实例(如
kubectl delete deployment old-service
) - 生产环境:
- 最后确认监控:调用量、下游依赖均为0,无未完成的长事务(如分布式事务)
- 优雅停机:发送
SIGTERM
信号,等待进程处理完剩余请求后退出(避免强制kill导致数据不一致) - 验证停止:通过
ps
/kubectl get pods
确认进程/容器已终止
2. 数据处理
根据数据留存要求,对旧服务数据进行分类处理:
- 需归档数据:如用户历史记录、业务日志,通过ETL工具迁移至归档存储(如对象存储、冷备数据库),并记录归档路径
- 可删除数据:临时缓存、测试数据,通过脚本批量删除(如
redis-cli keys "old-service:*" | xargs redis-cli del
) - 数据备份:下线前执行最后一次全量备份,备份文件保留至少3个月(用于应急查询)
3. 资源回收
彻底清理旧服务占用的所有资源,避免浪费:
- 计算资源:服务器/虚拟机/容器实例、K8s Deployment/StatefulSet、镜像仓库镜像
- 网络资源:域名/子域名(如
old-api.example.com
)、负载均衡器、安全组规则 - 存储资源:数据库实例/表、Redis集群/实例、消息队列topic/consumer group、ES索引
- 配置资源:配置中心配置(如Nacos/Apollo)、注册中心服务名、CI/CD流水线
五、下线后验证(T+1天至T+7天)
1. 业务验证
- 确认依赖旧服务的业务场景正常(通过新服务或替代方案)
- 检查核心指标(如转化率、下单量)是否与下线前一致,无异常波动
2. 残留检查
- 资源检查:通过云平台控制台/脚本确认所有资源已回收(如
aws ec2 describe-instances --filters "Name=tag:Service,Values=old-service"
) - 日志检查:搜索全量日志(如ELK),确认无新的调用请求(关键词:旧服务IP/域名/接口名)
- 代码检查:删除代码仓库中旧服务的代码(如
git rm -rf old-service/
),避免误部署
3. 回滚机制(应急场景)
若下线后出现严重问题(如发现未处理的核心调用),需在1小时内完成回滚:
- 恢复服务:重新部署旧服务(使用备份的镜像/代码),启动实例
- 恢复流量:在网关层重新路由流量至旧服务
- 恢复数据:若已删除数据,从备份中恢复
- 根因分析:同步排查遗漏的调用方,制定二次下线计划
六、风险与应对措施
风险类型 | 具体风险 | 应对措施 |
---|---|---|
流量残留 | 存在未发现的调用方(如内部定时任务) | 下线前通过全链路追踪扫描所有调用来源;预留1周观察期 |
数据丢失 | 误删需留存的数据 | 数据删除前执行备份;删除操作需双人复核 |
业务中断 | 新服务未完全替代旧服务功能 | 下线前进行全量功能测试;保留旧服务代码3个月 |
资源回收不彻底 | 遗漏部分资源(如隐藏的安全组规则) | 制定资源回收清单,逐项检查并标记完成状态 |
七、文档归档与复盘
-
文档归档:
- 整理下线全流程记录(含时间点、操作人、关键决策)
- 归档服务信息(接口文档、架构图)、数据归档路径、资源回收清单
- 存储位置:团队知识库(如Confluence)
-
复盘总结:
- 组织相关方召开复盘会,总结经验教训(如"未发现的调用方如何提前识别")
- 优化服务下线流程(如补充"定时任务排查清单")
八、时间规划示例
阶段 | 时间窗口 | 关键任务 |
---|---|---|
准备阶段 | T-30天至T-7天 | 依赖梳理、影响评估、相关方确认 |
灰度下线阶段 | T-7天至T-1天 | 流量逐步切换、监控剩余调用方 |
正式下线 | T日 | 停止服务、处理数据、回收资源 |
验证阶段 | T+1天至T+7天 | 业务验证、残留检查、问题修复 |
复盘归档 | T+10天 | 文档归档、流程优化 |
通过以上流程,可在保障业务安全的前提下,系统化完成旧服务下线,同时避免资源浪费和潜在风险。核心是"充分准备、渐进执行、全面验证",确保每一步都有数据支撑和回滚预案。