软件项目开发全流程 · 第 35 课 · 系统退役与迁移
1、"这个系统早该关了,但没人敢关"
公司里常有这么一套"僵尸系统":五年前的老后台,界面丑陋、文档全无,但还有几个老客户在用,还连着几个下游接口,还有定时任务在跑。没人想维护它,也没人敢关它。
系统退役(Decommissioning / Sunsetting) 是生命周期的最后一环,也是最容易被忽视的一环。本课讲:怎么安全、体面地"送走"一个系统。
2、退役不是"关机",是一场手术
为什么不能直接关?
直接关机的后果:
- 还有用户在用 → 投诉、业务中断
- 还有系统在调用它的 API → 下游崩溃
- 还有数据没迁走 → 永久丢失
- 合规要求保留数据 → 法律风险
- 还有定时任务依赖它 → 静默失败退役是一场需要规划的"手术",核心是:确认无人依赖 → 迁移 → 降级 → 关停 → 清理。
3、退役的决策:该不该关?
先问清楚:
| 问题 | 说明 |
|---|---|
| 还有谁在用? | 用户、内部系统、外部合作方、定时任务 |
| 替代方案是什么? | 新系统能覆盖它的所有功能吗? |
| 迁移成本 vs 维护成本 | 继续维护贵,还是迁移贵? |
| 合规/法律要求 | 数据要保留多久?有审计要求吗? |
| 技术债利息 | 它拖累多少新开发?(如老依赖、安全漏洞) |
常见退役决策:
- 完全退役:功能被新系统完全取代,直接关。
- 部分退役:只关掉某些模块,保留核心。
- 降级维护(Maintenance Mode):不再加功能,只修致命 bug,静待用户迁移完毕。
- 冻结(Freeze):不再变更,等到期日关停。
4、退役五步法
① 盘点依赖(谁在用它?)
↓
② 制定迁移路径(用户/数据/接口怎么走)
↓
③ 沟通与预告(提前通知,给迁移窗口)
↓
④ 灰度降级(先只读 → 再停写 → 再停服务)
↓
⑤ 关停与清理(下线 → 归档数据 → 回收资源 → 除名)① 盘点依赖——最容易漏的一步。要找全:
- 代码里对它的调用(grep 域名/服务名/SDK)
- 网关/负载均衡上的路由
- 数据库连接、消息队列订阅
- 定时任务、cron、脚本
- 报表、BI、数据仓库抽取任务
- 人(文档、Wiki、谁口头说过在用)
- 外部合作方(合同、对接文档)技巧:加监控埋点,观察一段时间真实流量——很多"没人用"的系统,其实还有暗流量。
② 迁移路径:
数据:导出 → 转换 → 导入新系统 → 校验 → 保留归档
用户:引导注册/切换 → 提供迁移工具 → 双轨过渡期
接口:通知下游改调用 → 提供兼容层/代理 → 到期下线③ 沟通与预告——提前、反复、多渠道通知:
- 提前 N 个月公告(视影响面),说明关停日期。
- 邮件、站内信、文档、客户经理逐户通知。
- 给出迁移指南和支持渠道。
- 到期前再次提醒(很多用户会忽略第一次)。
④ 灰度降级——别一步到位:
完整服务 → 只读模式(禁止写入,保留查询)
→ 停写 + 提示迁移
→ 停服务(返回 410 Gone / 友好提示)
→ 完全下线这样给了用户缓冲,也给了自己发现漏网依赖的机会。
⑤ 关停与清理:
□ 服务下线(先停流量,再停实例)
□ 数据归档(按合规要求保留,冷存储)
□ 依赖清理(停定时任务、删路由、撤 DNS)
□ 资源回收(机器、域名、证书、账号、密钥)
□ 文档更新(标注"已退役",链接到替代方案)
□ 代码归档(打 tag、归档 repo,别直接删)5、数据保留:关系统 ≠ 删数据
合规是硬约束。很多行业(金融、医疗)要求数据保留 N 年。
- 归档(Archive):数据搬到冷存储,可查但不可改
- 匿名化(Anonymize):删掉个人标识,保留统计价值
- 加密归档:合规 + 安全
- 明确保留期与销毁流程:到期依法销毁要点:退役方案里必须写清"数据怎么办"——否则可能违规,或被追责。
6、重写/替换式的"迁移"
如果退役是用新系统替代(而不是单纯关掉),这就是系统迁移(Migration):
新老并行(Parallel Run):
一段时间内,两套系统同时运行
流量按比例切(5% → 50% → 100%)
比对两边结果,确保一致
↓
确认新系统稳定后,停老系统"双跑(Dual-run)"的价值:能在真实流量下验证新系统,且回滚成本低。代价是维护两套(双倍成本),所以要限定双跑时长。
注意:迁移中最大的风险是数据一致性——两套系统写同一业务时,谁是"真相源"?通常用单一写入源 + 同步或双写 + 对账来保证。
7、退役的"软"侧面:人与文化
系统退役常伴随情绪阻力:
- 原作者的感情:"这可是我第一个系统。"
- 使用者的惯性:"我用惯了,懒得换。"
- 维护者的恐惧:"关了出事谁负责?"
应对:
- 用数据说话(真实使用量、维护成本)。
- 给足过渡期、给好迁移工具。
- 明确责任人(退役也要有 owner)。
- 庆祝——退役也是团队的成就(减少负担)。
8、常见误区
| 误区 | 问题 | 正解 |
|---|---|---|
| 直接关机 | 用户/依赖遭殃 | 盘点依赖、灰度降级 |
| 不盘点暗依赖 | 下游静默失败 | 埋点观察 + 全面 grep |
| 不提前通知 | 用户措手不及 | 提前多渠道预告 |
| 关停即删数据 | 合规违规、无法追溯 | 按保留期归档/匿名化 |
| 双跑无限期 | 成本翻倍 | 限定双跑窗口 |
| 代码/资源不清理 | 遗留隐患与成本 | 清理资源、归档代码 |
| 无 owner | 无人推进 | 指定退役负责人 |
9、动手实验 🎯
任务:为贯穿项目「团队任务清单」写一份退役预案(假设 v0 要被 v1 取代)。
- 依赖盘点:列出所有可能依赖"旧版"的地方(代码、路由、定时任务、文档、用户)。
- 决策表:填一张"该不该退役"的评估表(用户、替代方案、成本、合规)。
- 写迁移路径:数据、用户、接口各自怎么迁移;给出时间线(如 T-90 天公告)。
- 设计灰度降级:从"完整服务 → 只读 → 停写 → 下线"的每一步,写清楚做什么、观察什么。
- 数据保留方案:说明数据怎么归档、保留多久、谁来销毁。
- 写退役公告:起草一份给用户的关停通知(含日期、替代方案、迁移指南链接)。
- 清理清单:列一份"关停后要回收的资源"清单(机器、域名、证书、密钥、账号)。
- 反思:你身边有没有"该退役却没人敢动"的系统?如果让你推进,第一步会做什么?
下一课:全流程综合案例(结课)。
10、今天你带走的三句话
- 退役是手术,不是关机:盘点依赖 → 迁移 → 沟通 → 灰度降级 → 关停清理。
- 别漏"暗依赖":埋点观察真实流量,全面 grep 路由/任务/文档。
- 关系统 ≠ 删数据:按合规保留期归档/匿名化;替换式迁移用双跑 + 灰度。
下一课:全流程综合案例(结课)。