Arch Day 104: 遗留系统改造 — "在飞行中换引擎"
Arch Day 104: 遗留系统改造 — "在飞行中换引擎"
日期: 2026-07-12 (Day 104) 阶段: 第四阶段 - 高阶融合 标签: #遗留系统 #StranglerFig #防腐层 #数据迁移 #系统改造 #渐进式迁移
核心概念
遗留系统改造是"在飞行中换引擎"——最难的架构挑战之一
遗留系统改造之所以被称为架构师面临的最难挑战,不是因为技术本身有多复杂(虽然确实复杂),而是因为它同时涉及技术风险、业务连续性、组织政治和人员能力四个维度的挑战。
为什么遗留系统改造如此困难?
技术维度:
├── 代码量巨大(百万级LOC,无人完全理解)
├── 文档缺失("唯一的文档就是代码本身")
├── 测试缺失("改一行代码不知道会坏什么")
├── 技术栈过时(没人会维护的语言/框架)
└── 耦合严重("动一个模块,全系统抖三抖")
业务维度:
├── 24/7不能停("银行系统不能说停就停")
├── 数据不能丢("一笔交易都不能少")
├── 功能不能降("新系统至少要和旧的一样")
└── 用户无感知("切换对用户透明")
组织维度:
├── 旧系统维护团队的抵触("你要革我命?")
├── 管理层的恐惧("万一搞砸了谁负责?")
├── 预算争夺("这个投资什么时候能回本?")
└── 人才缺乏("谁既懂老系统又懂新技术?")
2025-2026年遗留系统改造的新动力:
根据行业趋势,遗留系统改造的紧迫性在加速:
- 大型机人才退休潮——懂COBOL的工程师越来越少
- AI和数据驱动业务需要现代化数据架构
- 云原生技术成熟,改造的技术风险降低
- 监管要求系统韧性和灾备能力提升
- 竞争对手的数字化转型压力
知识点详解
一、评估框架:改造 vs 替换 vs 封装 vs 退役
在动手之前,最重要的决策是:这个遗留系统应该怎么处理?
四种策略
┌──────────────┐ ┌──────────────┐
│ 改造 │ │ 替换 │
│ (Modernize) │ │ (Replace) │
│ │ │ │
│ 渐进式迁移 │ │ 全新系统替代 │
│ 保留核心逻辑 │ │ 推倒重来 │
│ 风险中等 │ │ 风险最高 │
└──────────────┘ └──────────────┘
┌──────────────┐ ┌──────────────┐
│ 封装 │ │ 退役 │
│ (Encapsulate)│ │ (Retire) │
│ │ │ │
│ 包一层API │ │ 关闭系统 │
│ 内部不动 │ │ 数据归档 │
│ 风险最低 │ │ 最简单 │
└──────────────┘ └──────────────┘
决策矩阵
| 因素 | 改造 | 替换 | 封装 | 退役 |
|---|---|---|---|---|
| 业务价值高 | 首选 | 可选 | 次选 | 不适用 |
| 业务价值低 | 不值得 | 不值得 | 短期方案 | 首选 |
| 技术风险高 | 谨慎 | 考虑 | 安全选择 | 考虑 |
| 时间紧迫 | 不适合 | 不适合 | 首选 | 可能 |
| 预算充足 | 首选 | 可选 | 次选 | 简单 |
| 预算有限 | 分期 | 不适合 | 首选 | 首选 |
| 团队能力强 | 首选 | 可选 | 不需要 | 简单 |
| 团队能力弱 | 困难 | 更困难 | 首选 | 简单 |
评估维度详解
评估每个遗留系统的六个维度(每项1-5分):
1. 业务价值 (Business Value): 1=低 5=核心
└── 这个系统对业务有多重要?
2. 技术质量 (Technical Quality): 1=腐烂 5=良好
└── 代码质量、测试覆盖、文档完整度
3. 变更频率 (Change Frequency): 1=几乎不变 5=频繁变更
└── 多久需要修改一次功能?
4. 运维成本 (Maintenance Cost): 1=低 5=极高
└── 维护这个系统需要多少人力/成本?
5. 风险等级 (Risk Level): 1=低风险 5=高风险
└── 改造过程中出问题的影响有多大?
6. 技术债严重度 (Tech Debt Severity): 1=轻 5=极重
└── 技术债对未来发展的阻碍有多大?
决策矩阵:
├── 高业务价值 + 低技术质量 + 高变更频率 → 改造(最优先)
├── 高业务价值 + 极低技术质量 → 替换(改造成本可能超过替换)
├── 高业务价值 + 低变更频率 → 封装(投入产出比最高)
├── 低业务价值 + 高运维成本 → 退役(减少浪费)
└── 高风险 + 任何策略 → 渐进式+充分测试
二、绞杀者模式(Strangler Fig Pattern)深度
模式起源
Martin Fowler受到自然界"绞杀榕"的启发提出这个模式——绞杀榕从其他树的树冠开始生长,根系逐渐包裹宿主树,最终宿主树死亡,绞杀榕取而代之。
这个比喻完美描述了遗留系统改造的理想过程:新系统逐步接管旧系统的功能,而非一次性替换。
四个阶段
阶段1: 识别(Identify)
┌─────────────────────────────┐
│ 旧系统 │
│ ┌────┐ ┌────┐ ┌────┐ │
│ │ A │ │ B │ │ C │ ... │
│ └────┘ └────┘ └────┘ │
│ 识别可独立迁移的功能模块 │
└─────────────────────────────┘
阶段2: 抽取(Extract)
┌──────────┐ ┌──────────────┐
│ 新服务A │ │ 旧系统 │
│ │ │ ┌────┐ ┌────┐│
│ (重写) │ │ │ B │ │ C ││
│ │ │ └────┘ └────┘│
└──────────┘ └──────────────┘
新建微服务重写功能A
阶段3: 重定向(Redirect)
┌──────────────────┐
│ 路由层/代理 │
│ (API Gateway) │
└─┬──────────┬─────┘
│ │
▼ ▼
┌──────────┐ ┌──────────────┐
│ 新服务A │ │ 旧系统 │
│ ← 流量 │ │ ┌────┐ ┌────┐│
│ │ │ │ B │ │ C ││
└──────────┘ │ └────┘ └────┘│
└──────────────┘
流量逐步从旧系统路由到新服务
阶段4: 退役(Retire)
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 新服务A │ │ 新服务B │ │ 新服务C │
│ │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘
旧系统完全退役
关键实施细节
识别阶段的方法:
如何选择第一个迁移的模块?
优先选择:
├── 变更频率高的模块(迁移后收益最大)
├── 耦合度低的模块(迁移风险最小)
├── 业务边界清晰的模块(容易定义接口)
└── 团队最熟悉的模块(减少认知负担)
避免先迁移:
├── 核心交易模块(风险太高)
├── 与多个模块深度耦合的模块(牵一发动全身)
├── 数据模型最复杂的模块(数据迁移难度大)
└── 团队不了解的模块(认知风险)
路由层设计:
路由层是绞杀者模式的核心组件——它决定每个请求去旧系统还是新服务:
路由策略:
├── 路径路由: /api/users → 新服务, /api/legacy/* → 旧系统
├── 百分比路由: 10%流量→新服务, 90%→旧系统(金丝雀)
├── 用户路由: 白名单用户→新服务, 其余→旧系统
├── Feature Flag: 基于功能开关切换
└── 数据路由: 新用户→新服务, 存量用户→旧系统
技术实现:
├── API Gateway (Kong/APISIX/Envoy)
├── 反向代理 (Nginx/HAProxy)
├── Service Mesh (Istio)
└── 应用层路由 (BFF)
2025-2026年绞杀者模式的最新实践
根据最新的行业实践,关键经验包括:
- 不要同时转换整个系统:实施增量变更,验证结果,然后有条不紊地推进
- 可观测性是关键:增量改造只有在能够准确测量系统健康时才有效
- 保守提取:从小处开始——避免大规模的初始提取。维护严格的API契约。避免遗留系统和新服务之间共享数据库
- 与数据流结合:使用Kafka等数据流平台实现遗留系统和新系统之间的数据同步,避免"双写"反模式
三、防腐层(Anti-Corruption Layer)设计
什么是防腐层?
防腐层是DDD中的重要模式——在新系统和旧系统之间建立一个翻译层,防止旧系统的"坏"模型"污染"新系统的设计。
Anti-Corruption Layer (ACL)
┌───────────────────────┐
新系统 │ 翻译/适配/转换 │ 旧系统
(新领域模型) ◄────▶│ │◄────▶ (旧数据模型)
│ ├── Model Translator │
│ ├── Facade │
│ └── Adapter │
└───────────────────────┘
防腐层的三个组件
1. Facade(外观)
└── 为旧系统提供简化接口
└── 隐藏旧系统的复杂性
2. Adapter(适配器)
└── 将旧系统的接口转换为新系统期望的接口
└── 处理协议差异(SOAP→REST, CSV→JSON等)
3. Translator(翻译器)
└── 将旧系统的领域模型翻译为新系统的领域模型
└── 处理概念差异(旧系统的"客户"≠新系统的"用户")
防腐层实现示例
# 旧系统的数据模型(COBOL系统产生的格式)
class LegacyCustomerRecord:
CUST_NO = "0012345" # 7位客户号
CUST_NM = "ZHANG SAN " # 固定长度,大写
ACCT_BAL = "000123456" # 9位整数,单位分
CUST_STS = "A" # A=Active, I=Inactive
OPEN_DT = "20200115" # YYYYMMDD格式
# 新系统的领域模型(现代设计)
@dataclass
class Customer:
id: str # UUID
legacy_id: str # 保留旧ID用于追溯
name: str
balance: Decimal
status: CustomerStatus # Enum
created_at: datetime
# 防腐层 - Translator
class CustomerTranslator:
def from_legacy(self, record: LegacyCustomerRecord) -> Customer:
return Customer(
id=str(uuid4()),
legacy_id=record.CUST_NO.strip(),
name=record.CUST_NM.strip().title(), # "ZHANG SAN" → "Zhang San"
balance=Decimal(record.ACCT_BAL) / 100, # 分→元
status=self._map_status(record.CUST_STS),
created_at=datetime.strptime(record.OPEN_DT, "%Y%m%d")
)
def to_legacy(self, customer: Customer) -> LegacyCustomerRecord:
record = LegacyCustomerRecord()
record.CUST_NO = customer.legacy_id.zfill(7)
record.CUST_NM = customer.name.upper().ljust(15)
record.ACCT_BAL = str(int(customer.balance * 100)).zfill(9)
record.CUST_STS = self._reverse_map_status(customer.status)
record.OPEN_DT = customer.created_at.strftime("%Y%m%d")
return record
def _map_status(self, legacy_status: str) -> CustomerStatus:
mapping = {"A": CustomerStatus.ACTIVE, "I": CustomerStatus.INACTIVE}
return mapping.get(legacy_status, CustomerStatus.UNKNOWN)
# 防腐层 - Facade + Adapter
class LegacyCustomerService:
"""隐藏旧系统的SOAP接口复杂性"""
def __init__(self, soap_client, translator):
self.client = soap_client
self.translator = translator
def get_customer(self, customer_id: str) -> Customer:
# Adapter: SOAP → Python对象
legacy_record = self.client.call("GetCustomer", CUST_NO=customer_id)
# Translator: 旧模型 → 新模型
return self.translator.from_legacy(legacy_record)
四、渐进式数据迁移
数据迁移是遗留系统改造中最复杂也最容易出错的部分。
双写→同步→切换→清理
阶段1: 双写(Dual Write)
┌──────────┐
│ 新服务 │──写──▶ 新数据库
│ │──写──▶ 旧数据库(通过ACL)
└──────────┘
⚠️ 风险: 两个写入不是原子操作,可能不一致
解决: 使用事件驱动(写新库→发事件→旧库消费事件)
阶段2: 数据同步
┌──────────┐ ┌──────────┐
│ 旧数据库 │──CDC──▶ │ 新数据库 │
│ (Source) │ (Debezium)│ (Target) │
└──────────┘ └──────────┘
├── Change Data Capture捕获旧库变更
├── 实时同步到新库
└── 定期一致性校验
阶段3: 切换读写
┌──────────┐
│ 新服务 │──读写──▶ 新数据库 (主)
│ │──只读──▶ 旧数据库 (备)
└──────────┘
├── 新库成为主数据源
├── 旧库保持只读同步(回滚用)
└── 监控数据一致性
阶段4: 清理
┌──────────┐
│ 新服务 │──读写──▶ 新数据库
└──────────┘
├── 停止向旧库同步
├── 旧数据库数据归档
├── 旧数据库退役
└── 保留归档数据(合规要求)
双写的危险和替代方案
"双写"是最常见但也是最危险的数据迁移反模式:
双写反模式:
App → 写新库 (成功)
App → 写旧库 (失败!) ← 数据不一致!
更安全的替代方案:
方案1: 事件驱动双写
App → 写新库 → 发布事件 → 旧库消费者写旧库
优点: 最终一致性保证
缺点: 旧库数据有延迟
方案2: CDC(Change Data Capture)
App → 写旧库(不改现有逻辑)
旧库 → CDC工具(Debezium) → 新库
优点: 零代码改动,最安全
缺点: 新库数据有延迟
方案3: 事务性发件箱(Transactional Outbox)
App → 在同一事务中写业务表+发件箱表
定时任务 → 读发件箱 → 同步到新库
优点: 数据一致性最强
缺点: 实现复杂
数据一致性校验
校验策略:
├── 实时校验: 每次写入后比较新旧库
│ └── 适合: 关键交易数据
│
├── 定期校验: 每小时/每天全量比对
│ └── 适合: 大量数据
│
└── 采样校验: 随机采样N%数据比对
└── 适合: 海量数据(全量比对太慢)
校验维度:
├── 计数校验: 新旧库记录总数一致
├── 聚合校验: SUM(amount)等聚合值一致
├── 明细校验: 逐条比对关键字段
└── 哈希校验: 对数据块计算哈希值比对
五、功能剥离策略
按域剥离(Domain-based)
旧单体系统:
┌──────────────────────────────────┐
│ 用户管理 │ 订单管理 │ 支付 │ 库存 │
└──────────────────────────────────┘
剥离顺序(按DDD限界上下文):
Phase 1: 用户管理 → User Service
Phase 2: 库存管理 → Inventory Service
Phase 3: 订单管理 → Order Service
Phase 4: 支付处理 → Payment Service(最后,因为最核心)
按能力剥离(Capability-based)
不是按业务域,而是按技术能力剥离:
Phase 1: 通知能力 → Notification Service(影响最小)
Phase 2: 报表能力 → Reporting Service(只读,低风险)
Phase 3: 搜索能力 → Search Service(Elasticsearch替代数据库全文搜索)
Phase 4: 认证能力 → Auth Service(安全关键,需谨慎)
按流量剥离(Traffic-based)
高流量路径优先迁移(收益最大):
Phase 1: 首页/搜索(>50%流量)→ 新系统
Phase 2: 商品详情 → 新系统
Phase 3: 购物车 → 新系统
Phase 4: 下单/支付 → 新系统(最后,最关键)
按风险剥离(Risk-based)
低风险模块先迁移(积累经验和信心):
Phase 1: 帮助中心/FAQ(零风险试水)
Phase 2: 用户设置/偏好(低风险)
Phase 3: 通知/消息(中低风险)
Phase 4: 交易/支付(高风险,有了经验再动)
六、遗留系统改造的组织挑战
技术挑战只占30%,组织挑战占70%。
政治因素
常见政治挑战:
├── "这是我建的系统"综合症
│ └── 旧系统维护者视改造为威胁
│ └── 对策: 让旧团队成员加入新团队,而非替换
│
├── "什么都不要动"恐惧
│ └── 管理层害怕改造风险
│ └── 对策: 渐进式改造+每步展示结果+快速回滚能力
│
├── "先做新功能"优先级之争
│ └── 业务永远觉得新功能比技术改造重要
│ └── 对策: 将改造与业务目标绑定("改造后新功能开发速度提升3x")
│
└── "这次肯定能一步到位"幻想
└── 管理层期望一次性解决所有问题
└── 对策: 明确改造是持续过程,展示分阶段路线图
预算挑战
改造预算的获取策略:
1. 量化当前成本:
"现在每个新功能需要2个月,改造后只需要2周"
"每年维护旧系统的人力成本是X万"
"旧系统的故障每次损失Y万"
2. 渐进式投资:
不是申请"3000万全面改造"
而是"先投100万做PoC,证明可行后再分期投入"
3. 绑定业务目标:
"改造不是为了技术,而是为了支撑明年的业务翻倍增长"
"新系统支持的XX功能能带来Y%的收入增长"
4. 风险驱动:
"旧系统最后一个懂的人明年退休"
"监管要求明年必须具备X能力,旧系统做不到"
人才挑战
人才困境:
├── 懂旧系统的人不想学新技术
├── 会新技术的人不愿接触旧系统
└── 两者都懂的人极度稀缺
对策:
├── 组建"桥梁团队": 旧系统专家 + 新技术专家配对
├── 知识传承计划: 在改造过程中记录旧系统的业务规则
├── 激励机制: 参与改造的人有技术成长和认可
└── 外部专家: 必要时引入有改造经验的咨询团队
对比分析
改造策略全面对比
| 维度 | 绞杀者模式 | Big Bang替换 | 封装(Wrap) | 重构(Refactor) |
|---|---|---|---|---|
| 风险 | 低-中 | 极高 | 最低 | 中 |
| 时间 | 长(月-年) | 中(如果成功) | 短 | 长 |
| 成本 | 中高 | 高 | 低 | 中 |
| 业务中断 | 最小 | 可能很大 | 无 | 小 |
| 技术债清理 | 彻底 | 彻底 | 不清理 | 部分 |
| 推荐度 | 首选 | 最后手段 | 权宜之计 | 特定场景 |
数据迁移策略对比
| 策略 | 一致性 | 复杂度 | 停机需求 | 适用数据量 |
|---|---|---|---|---|
| 停机迁移 | 最强 | 最低 | 有停机 | 小-中 |
| 双写 | 弱(风险) | 中 | 无 | 中 |
| CDC | 最终一致 | 中高 | 无 | 大 |
| 事件驱动 | 最终一致 | 高 | 无 | 大 |
| 蓝绿数据库 | 强 | 最高 | 极短 | 大 |
架构设计实操:设计"核心银行系统"改造路线图
场景
某城商银行的核心系统运行了15年,基于IBM大型机+COBOL,日均处理100万笔交易。面临的问题:COBOL人才稀缺、新功能开发周期6个月、无法支撑移动端业务增长、运维成本每年递增20%。
阶段0:评估(2个月)
assessment:
current_state:
technology: "IBM z/OS, COBOL, DB2, CICS"
codebase: "~200万行COBOL代码"
modules:
- name: "存款"
business_value: 5
change_frequency: 4
coupling: "高"
risk: 5
- name: "贷款"
business_value: 5
change_frequency: 3
coupling: "高"
risk: 5
- name: "客户信息"
business_value: 4
change_frequency: 4
coupling: "中"
risk: 3
- name: "报表/查询"
business_value: 3
change_frequency: 2
coupling: "低"
risk: 1
- name: "渠道接入"
business_value: 4
change_frequency: 5
coupling: "中"
risk: 2
decision:
报表_查询: "先迁移(低风险+低耦合)"
渠道接入: "次迁移(业务收益大+耦合中等)"
客户信息: "第三迁移(为后续核心模块铺路)"
存贷核心: "最后迁移(风险最高,需要充分经验)"
阶段1:基础设施准备+报表迁移(6个月)
目标: 建立新技术基础设施 + 迁移低风险模块
┌──────────────────────────────────────────┐
│ 路由层 (API Gateway) │
│ ├── /api/reports/* → 新报表服务 │
│ └── /* → 旧核心系统 │
└──────────────────────────────────────────┘
新建:
├── Kubernetes集群(阿里云ACK/AWS EKS)
├── 新数据库(OceanBase/PostgreSQL)
├── CDC管道(旧DB2 → Debezium → 新数据库)
├── 报表服务(Java/Spring Boot)
├── API Gateway(APISIX)
└── 监控体系(Prometheus+Grafana)
迁移:
├── 报表数据CDC同步(旧DB2 → 新库)
├── 报表查询功能重写
├── 新旧报表结果比对验证
└── 流量逐步切到新报表服务
成果:
├── 报表查询速度提升10x
├── 团队积累改造经验
├── 验证CDC+路由层方案可行
└── 管理层看到初步成果
阶段2:渠道层迁移+API化(6个月)
目标: 将旧系统的渠道接入层迁移到新平台
┌──────────────────────────────────────────┐
│ API Gateway │
│ ├── /api/reports/* → 新报表服务 │
│ ├── /api/mobile/* → 新渠道服务 │
│ ├── /api/online/* → 新渠道服务 │
│ └── /* → 旧核心系统 │
└──────────────────────────────────────────┘
新建:
├── BFF层(为移动端/网银提供API)
├── 防腐层(ACL)(翻译旧系统数据模型)
└── 新的移动端/网银前端
关键设计:
├── 新渠道服务通过ACL调用旧核心系统
│ └── 新系统用现代API设计,ACL负责翻译为旧系统协议
├── 旧系统对外接口不变(不修改旧代码)
└── 新功能只在新渠道服务上开发
成果:
├── 新功能开发周期从6个月缩短到2周
├── 移动端体验显著提升
├── 为后续核心迁移建立ACL基础
└── 业务侧看到明显价值
阶段3:客户信息域迁移(6个月)
目标: 迁移客户信息管理,为核心域迁移铺路
数据迁移策略:
1. CDC同步: DB2客户表 → Debezium → OceanBase新客户表
2. 双读验证: 新旧库同时读取,比对结果(持续2周)
3. 切换写入: 新库成为主写入源
4. 反向同步: 新库 → 旧库(旧核心系统还需要读客户数据)
5. 最终清理: 旧核心系统改为从新客户服务读取
关键挑战:
├── 客户数据模型差异大(旧系统用编号,新系统用UUID)
├── 旧系统多处硬编码了客户表结构
└── 需要在旧系统代码中增加路由逻辑
阶段4:存贷核心迁移(12-18个月)
目标: 最终将存贷款核心迁移到新平台(最高风险阶段)
策略: 极致谨慎的金丝雀迁移
├── 先迁移"定期存款"(相对简单)
│ └── 新建定期存款微服务
│ └── 新客户→新服务,存量客户→旧系统
│ └── 验证3个月无问题
│
├── 再迁移"活期存款"(最核心)
│ └── 金丝雀: 1%客户→新系统
│ └── 验证1个月 → 扩大到10% → 50% → 100%
│
├── 最后迁移"贷款"
│ └── 同样的金丝雀策略
│
└── 旧系统退役
└── 所有功能确认迁移完成
└── 数据归档(保留7年+)
└── 旧大型机退役
总时间线: 约30-36个月
AI增强
AI在遗留系统改造中的应用
-
代码理解:
- AI分析百万行COBOL代码,生成业务规则文档
- 自动识别代码中的隐含业务逻辑
- 生成旧系统的依赖关系图
-
代码翻译:
- COBOL → Java/Python的AI辅助翻译
- 注意:AI翻译需要人工审查,不能盲信
- 适合低复杂度模块的批量翻译
-
测试生成:
- AI根据旧系统行为生成测试用例
- 自动发现旧系统的边界条件和异常处理
- 生成新旧系统的对比测试
-
风险评估:
- AI分析代码变更影响范围
- 预测迁移可能的风险点
- 推荐迁移顺序
2025-2026年的新趋势
大型机COBOL系统改造正在借助AI加速——但完全自动化的翻译仍然不现实。AI最大的价值在于理解旧代码和生成测试,而非直接替换人类的设计决策。
Web3关联
智能合约的"遗留问题"
区块链世界也有遗留系统问题:
- 不可变性:智能合约部署后无法修改,"遗留合约"永远存在
- 代理模式:通过Proxy合约实现"可升级",本质上就是"封装旧系统"
- 迁移挑战:从V1合约迁移到V2,需要迁移所有状态数据和用户
Uniswap V2→V3的迁移就是一个典型的"绞杀者模式":V3逐步接管流动性,V2继续运行但不再开发新功能。
今日思考
遗留系统改造是一场"持久战"而非"闪电战"。Martin Fowler的绞杀者模式之所以成为行业标准,是因为它尊重了一个基本事实:你不能停下业务来做技术改造。
最大的教训来自组织层面——技术方案可以设计得很完美,但如果没有管理层的支持、团队的参与、业务的理解,改造必然失败。
2025-2026年的新变化:AI正在降低理解和翻译旧代码的成本,CDC工具(Debezium等)让数据迁移更加安全,云原生平台让新系统的搭建更加快速。改造的门槛在降低,但核心挑战——组织和文化——仍然需要人来解决。
面试题
Q1: 如何推动遗留系统改造?
30秒回答:三步走——第一,量化痛点(运维成本X万/年、新功能周期6个月、人才流失风险);第二,渐进式方案(不是大爆炸替换,而是绞杀者模式分期改造);第三,快速展示价值(先迁移低风险模块,用结果说服管理层继续投资)。
2分钟详细回答:
推动遗留系统改造需要同时解决技术和组织两方面的问题:
说服管理层:
- 量化当前成本:每年运维X万、新功能周期6个月、每次故障损失Y万
- 量化风险:最后一个懂系统的人明年退休、监管要求无法满足
- 提出渐进方案:先投100万做PoC,3个月出结果
- 绑定业务目标:改造后支撑移动业务增长
技术策略:
- 绞杀者模式:新系统逐步接管旧系统功能
- 从低风险模块开始:积累经验、建立信心
- 防腐层隔离:新旧系统互不污染
- CDC数据同步:避免停机迁移
关键成功因素:
- 让旧系统团队参与(而非被替换)
- 每个阶段都有可度量的成果
- 随时可以暂停(不是不可逆的决策)
Q2: 绞杀者模式的关键步骤?
30秒回答:四步——识别(选择低风险、低耦合的模块先迁移)→ 抽取(用新技术重写该模块为独立服务)→ 重定向(通过路由层将流量从旧系统切到新服务)→ 退役(确认无误后关闭旧系统对应模块)。
2分钟详细回答:
- 识别:优先选择变更频率高+耦合度低+团队熟悉的模块。避免先动核心交易模块
- 抽取:用新技术栈重写,建立防腐层翻译新旧模型。新服务的API应面向未来设计,不要复制旧系统的设计
- 重定向:通过API Gateway/反向代理做路由。可以按路径、百分比、用户维度灰度切换。金丝雀策略逐步切量
- 退役:确认新服务稳定后,停止旧模块。数据归档保留。更新文档
关键经验:
- 保守提取,从小处开始
- 可观测性是关键——没有监控就不要切流量
- 避免双写反模式,用CDC或事件驱动做数据同步
- 整个过程可能需要数年,需要持续的组织承诺
学习资源
- Strangler Fig Pattern | ThoughtWorks — 绞杀者模式详解
- Strangler Fig with Data Streaming | Kai Waehner — 数据流+绞杀者模式
- Strangler Fig Pattern Explained | DaydreamSoft — 增量改造实践
- Big Bang vs Progressive Modernization | AppsTek — 改造策略对比
- Modernizing Legacy with Strangler Fig | Brainhub — 绞杀者模式实践
- Legacy Modernization Best Practices | STEP Software — 最佳实践+风险+财务影响
明日预告
明天我们将学习技术债管理(高级)——技术债是"今天的捷径,明天的利息",但不是所有技术债都该还。我们将学习Ward Cunningham四象限分类、SQALE量化方法论、以及如何把技术债翻译成管理层能理解的语言。