架构设计模式之绞杀者模式(Strangler Fig Pattern):渐进式重构遗留系统的终极武器

架构设计模式之绞杀者模式(Strangler Fig Pattern):渐进式重构遗留系统的终极武器

从"推倒重来"到"温水煮青蛙",一种让遗留系统优雅谢幕的架构策略

📑 目录


一、引言:当"推倒重来"成为噩梦

在软件生命周期中,遗留系统(Legacy System) 是每个技术团队都会面对的棘手问题。它们可能:

  • 代码量超过百万行,耦合严重,牵一发而动全身
  • 技术栈老旧(如Struts 1.x、EJB 2.x),难以招募维护人才
  • 业务逻辑复杂,文档缺失,无人敢轻易动刀

面对这样的系统,传统思路有两种:

  • 推倒重来(Big Bang Rewrite) :从零开发新系统,一次性替换旧系统 ------ 风险极高,极易失败(历史上Google+、Windows Vista等项目均是前车之鉴)
  • 冻结旧系统,只做维护 ------ 业务无法演进,系统逐渐腐化

绞杀者模式(Strangler Fig Pattern) 提供了第三条路:以渐进、可控、零中断的方式,用新系统逐步替换旧系统,最终完成现代化的优雅转身。


二、什么是绞杀者模式?

绞杀者模式(Strangler Fig Pattern) 的名称源自热带雨林中的绞杀榕(Strangler Fig)
绞杀榕的种子落在宿主树的枝干上,发芽后长出气生根,气生根向下缠绕宿主树,逐渐伸入土壤。随着绞杀榕根系壮大,它不断夺取宿主树的养分和阳光,最终宿主树因营养枯竭而死亡,绞杀榕则成长为独立的参天大树。
#mermaid-svg-uKfjtmOfzkf83tkL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-uKfjtmOfzkf83tkL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-uKfjtmOfzkf83tkL .error-icon{fill:#552222;}#mermaid-svg-uKfjtmOfzkf83tkL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-uKfjtmOfzkf83tkL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-uKfjtmOfzkf83tkL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-uKfjtmOfzkf83tkL .marker.cross{stroke:#333333;}#mermaid-svg-uKfjtmOfzkf83tkL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-uKfjtmOfzkf83tkL p{margin:0;}#mermaid-svg-uKfjtmOfzkf83tkL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-uKfjtmOfzkf83tkL .cluster-label text{fill:#333;}#mermaid-svg-uKfjtmOfzkf83tkL .cluster-label span{color:#333;}#mermaid-svg-uKfjtmOfzkf83tkL .cluster-label span p{background-color:transparent;}#mermaid-svg-uKfjtmOfzkf83tkL .label text,#mermaid-svg-uKfjtmOfzkf83tkL span{fill:#333;color:#333;}#mermaid-svg-uKfjtmOfzkf83tkL .node rect,#mermaid-svg-uKfjtmOfzkf83tkL .node circle,#mermaid-svg-uKfjtmOfzkf83tkL .node ellipse,#mermaid-svg-uKfjtmOfzkf83tkL .node polygon,#mermaid-svg-uKfjtmOfzkf83tkL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-uKfjtmOfzkf83tkL .rough-node .label text,#mermaid-svg-uKfjtmOfzkf83tkL .node .label text,#mermaid-svg-uKfjtmOfzkf83tkL .image-shape .label,#mermaid-svg-uKfjtmOfzkf83tkL .icon-shape .label{text-anchor:middle;}#mermaid-svg-uKfjtmOfzkf83tkL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-uKfjtmOfzkf83tkL .rough-node .label,#mermaid-svg-uKfjtmOfzkf83tkL .node .label,#mermaid-svg-uKfjtmOfzkf83tkL .image-shape .label,#mermaid-svg-uKfjtmOfzkf83tkL .icon-shape .label{text-align:center;}#mermaid-svg-uKfjtmOfzkf83tkL .node.clickable{cursor:pointer;}#mermaid-svg-uKfjtmOfzkf83tkL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-uKfjtmOfzkf83tkL .arrowheadPath{fill:#333333;}#mermaid-svg-uKfjtmOfzkf83tkL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-uKfjtmOfzkf83tkL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-uKfjtmOfzkf83tkL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uKfjtmOfzkf83tkL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-uKfjtmOfzkf83tkL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uKfjtmOfzkf83tkL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-uKfjtmOfzkf83tkL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-uKfjtmOfzkf83tkL .cluster text{fill:#333;}#mermaid-svg-uKfjtmOfzkf83tkL .cluster span{color:#333;}#mermaid-svg-uKfjtmOfzkf83tkL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-uKfjtmOfzkf83tkL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-uKfjtmOfzkf83tkL rect.text{fill:none;stroke-width:0;}#mermaid-svg-uKfjtmOfzkf83tkL .icon-shape,#mermaid-svg-uKfjtmOfzkf83tkL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-uKfjtmOfzkf83tkL .icon-shape p,#mermaid-svg-uKfjtmOfzkf83tkL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-uKfjtmOfzkf83tkL .icon-shape .label rect,#mermaid-svg-uKfjtmOfzkf83tkL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-uKfjtmOfzkf83tkL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-uKfjtmOfzkf83tkL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-uKfjtmOfzkf83tkL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 绞杀榕的隐喻
种子落在宿主树上
气生根缠绕宿主
根系扎根土壤
夺取养分,宿主枯死
绞杀榕成为独立大树

在软件架构领域,绞杀者模式的含义是:

在不停止旧系统运行的前提下,通过一个代理层(Facade/API Gateway),将功能逐个从旧系统迁移到新系统,最终全部替换完成后,安全退役旧系统。

这种模式的核心优势是业务零中断、风险可控、持续交付 ,是Martin Fowler在其博客中极力推荐的遗留系统现代化策略


三、核心运作机制:三阶段渐进替换

绞杀者模式通常分为三个关键阶段,且三个阶段是逐渐演进的,前后存在重叠期

阶段一:🔀 拦截与路由

在旧系统前部署一个代理层(API网关/反向代理) ,拦截所有客户端请求。

  • 该代理层作为唯一入口,对所有请求进行统一路由。
  • 初期:代理层将所有请求转发至旧系统,新旧用户无感知。

#mermaid-svg-LQQq39NnkGo3Q66n{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-LQQq39NnkGo3Q66n .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-LQQq39NnkGo3Q66n .error-icon{fill:#552222;}#mermaid-svg-LQQq39NnkGo3Q66n .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-LQQq39NnkGo3Q66n .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-LQQq39NnkGo3Q66n .marker{fill:#333333;stroke:#333333;}#mermaid-svg-LQQq39NnkGo3Q66n .marker.cross{stroke:#333333;}#mermaid-svg-LQQq39NnkGo3Q66n svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-LQQq39NnkGo3Q66n p{margin:0;}#mermaid-svg-LQQq39NnkGo3Q66n .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-LQQq39NnkGo3Q66n .cluster-label text{fill:#333;}#mermaid-svg-LQQq39NnkGo3Q66n .cluster-label span{color:#333;}#mermaid-svg-LQQq39NnkGo3Q66n .cluster-label span p{background-color:transparent;}#mermaid-svg-LQQq39NnkGo3Q66n .label text,#mermaid-svg-LQQq39NnkGo3Q66n span{fill:#333;color:#333;}#mermaid-svg-LQQq39NnkGo3Q66n .node rect,#mermaid-svg-LQQq39NnkGo3Q66n .node circle,#mermaid-svg-LQQq39NnkGo3Q66n .node ellipse,#mermaid-svg-LQQq39NnkGo3Q66n .node polygon,#mermaid-svg-LQQq39NnkGo3Q66n .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-LQQq39NnkGo3Q66n .rough-node .label text,#mermaid-svg-LQQq39NnkGo3Q66n .node .label text,#mermaid-svg-LQQq39NnkGo3Q66n .image-shape .label,#mermaid-svg-LQQq39NnkGo3Q66n .icon-shape .label{text-anchor:middle;}#mermaid-svg-LQQq39NnkGo3Q66n .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-LQQq39NnkGo3Q66n .rough-node .label,#mermaid-svg-LQQq39NnkGo3Q66n .node .label,#mermaid-svg-LQQq39NnkGo3Q66n .image-shape .label,#mermaid-svg-LQQq39NnkGo3Q66n .icon-shape .label{text-align:center;}#mermaid-svg-LQQq39NnkGo3Q66n .node.clickable{cursor:pointer;}#mermaid-svg-LQQq39NnkGo3Q66n .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-LQQq39NnkGo3Q66n .arrowheadPath{fill:#333333;}#mermaid-svg-LQQq39NnkGo3Q66n .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-LQQq39NnkGo3Q66n .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-LQQq39NnkGo3Q66n .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LQQq39NnkGo3Q66n .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-LQQq39NnkGo3Q66n .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LQQq39NnkGo3Q66n .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-LQQq39NnkGo3Q66n .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-LQQq39NnkGo3Q66n .cluster text{fill:#333;}#mermaid-svg-LQQq39NnkGo3Q66n .cluster span{color:#333;}#mermaid-svg-LQQq39NnkGo3Q66n div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-LQQq39NnkGo3Q66n .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-LQQq39NnkGo3Q66n rect.text{fill:none;stroke-width:0;}#mermaid-svg-LQQq39NnkGo3Q66n .icon-shape,#mermaid-svg-LQQq39NnkGo3Q66n .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-LQQq39NnkGo3Q66n .icon-shape p,#mermaid-svg-LQQq39NnkGo3Q66n .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-LQQq39NnkGo3Q66n .icon-shape .label rect,#mermaid-svg-LQQq39NnkGo3Q66n .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-LQQq39NnkGo3Q66n .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-LQQq39NnkGo3Q66n .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-LQQq39NnkGo3Q66n :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 100%流量
客户端
代理层/API网关
旧系统/单体应用

阶段二:🌱 逐步替换(共存期)

这是最核心的阶段,也是持续时间最长的阶段。

  • 团队从旧系统中识别出边界清晰的功能模块,用新技术栈独立构建新服务。
  • 代理层根据路由规则(如HTTP Header、用户ID、URI路径) ,将部分请求逐步切换到新服务。
  • 新旧系统并行运行,共同为业务提供服务。

#mermaid-svg-IRrlzN3jP7StQY95{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IRrlzN3jP7StQY95 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IRrlzN3jP7StQY95 .error-icon{fill:#552222;}#mermaid-svg-IRrlzN3jP7StQY95 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IRrlzN3jP7StQY95 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IRrlzN3jP7StQY95 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IRrlzN3jP7StQY95 .marker.cross{stroke:#333333;}#mermaid-svg-IRrlzN3jP7StQY95 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IRrlzN3jP7StQY95 p{margin:0;}#mermaid-svg-IRrlzN3jP7StQY95 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IRrlzN3jP7StQY95 .cluster-label text{fill:#333;}#mermaid-svg-IRrlzN3jP7StQY95 .cluster-label span{color:#333;}#mermaid-svg-IRrlzN3jP7StQY95 .cluster-label span p{background-color:transparent;}#mermaid-svg-IRrlzN3jP7StQY95 .label text,#mermaid-svg-IRrlzN3jP7StQY95 span{fill:#333;color:#333;}#mermaid-svg-IRrlzN3jP7StQY95 .node rect,#mermaid-svg-IRrlzN3jP7StQY95 .node circle,#mermaid-svg-IRrlzN3jP7StQY95 .node ellipse,#mermaid-svg-IRrlzN3jP7StQY95 .node polygon,#mermaid-svg-IRrlzN3jP7StQY95 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IRrlzN3jP7StQY95 .rough-node .label text,#mermaid-svg-IRrlzN3jP7StQY95 .node .label text,#mermaid-svg-IRrlzN3jP7StQY95 .image-shape .label,#mermaid-svg-IRrlzN3jP7StQY95 .icon-shape .label{text-anchor:middle;}#mermaid-svg-IRrlzN3jP7StQY95 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IRrlzN3jP7StQY95 .rough-node .label,#mermaid-svg-IRrlzN3jP7StQY95 .node .label,#mermaid-svg-IRrlzN3jP7StQY95 .image-shape .label,#mermaid-svg-IRrlzN3jP7StQY95 .icon-shape .label{text-align:center;}#mermaid-svg-IRrlzN3jP7StQY95 .node.clickable{cursor:pointer;}#mermaid-svg-IRrlzN3jP7StQY95 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IRrlzN3jP7StQY95 .arrowheadPath{fill:#333333;}#mermaid-svg-IRrlzN3jP7StQY95 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IRrlzN3jP7StQY95 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IRrlzN3jP7StQY95 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IRrlzN3jP7StQY95 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IRrlzN3jP7StQY95 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IRrlzN3jP7StQY95 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IRrlzN3jP7StQY95 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IRrlzN3jP7StQY95 .cluster text{fill:#333;}#mermaid-svg-IRrlzN3jP7StQY95 .cluster span{color:#333;}#mermaid-svg-IRrlzN3jP7StQY95 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IRrlzN3jP7StQY95 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IRrlzN3jP7StQY95 rect.text{fill:none;stroke-width:0;}#mermaid-svg-IRrlzN3jP7StQY95 .icon-shape,#mermaid-svg-IRrlzN3jP7StQY95 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IRrlzN3jP7StQY95 .icon-shape p,#mermaid-svg-IRrlzN3jP7StQY95 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IRrlzN3jP7StQY95 .icon-shape .label rect,#mermaid-svg-IRrlzN3jP7StQY95 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IRrlzN3jP7StQY95 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IRrlzN3jP7StQY95 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IRrlzN3jP7StQY95 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 切换规则
老用户/旧功能
灰度用户/新功能
特定URI
客户端
代理层/API网关
旧系统
新服务A
新服务B
旧数据库
新数据库

阶段三:🗑️ 淘汰旧系统

当所有功能都被迁移到新系统后,旧系统再无流量。

  • 此时可安全地下线旧系统,释放服务器资源
  • 最终移除代理层,让客户端直接访问新系统(或保留代理层作为统一入口)。
  • 项目里程碑完成

四、模式全景流程图

下面用Mermaid绘制完整的绞杀者模式演进全貌,展示三个阶段的衔接关系:
#mermaid-svg-CGs7sqBjbjXits4z{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-CGs7sqBjbjXits4z .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-CGs7sqBjbjXits4z .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-CGs7sqBjbjXits4z .error-icon{fill:#552222;}#mermaid-svg-CGs7sqBjbjXits4z .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CGs7sqBjbjXits4z .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-CGs7sqBjbjXits4z .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CGs7sqBjbjXits4z .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CGs7sqBjbjXits4z .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-CGs7sqBjbjXits4z .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CGs7sqBjbjXits4z .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CGs7sqBjbjXits4z .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CGs7sqBjbjXits4z .marker.cross{stroke:#333333;}#mermaid-svg-CGs7sqBjbjXits4z svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CGs7sqBjbjXits4z p{margin:0;}#mermaid-svg-CGs7sqBjbjXits4z .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CGs7sqBjbjXits4z .cluster-label text{fill:#333;}#mermaid-svg-CGs7sqBjbjXits4z .cluster-label span{color:#333;}#mermaid-svg-CGs7sqBjbjXits4z .cluster-label span p{background-color:transparent;}#mermaid-svg-CGs7sqBjbjXits4z .label text,#mermaid-svg-CGs7sqBjbjXits4z span{fill:#333;color:#333;}#mermaid-svg-CGs7sqBjbjXits4z .node rect,#mermaid-svg-CGs7sqBjbjXits4z .node circle,#mermaid-svg-CGs7sqBjbjXits4z .node ellipse,#mermaid-svg-CGs7sqBjbjXits4z .node polygon,#mermaid-svg-CGs7sqBjbjXits4z .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CGs7sqBjbjXits4z .rough-node .label text,#mermaid-svg-CGs7sqBjbjXits4z .node .label text,#mermaid-svg-CGs7sqBjbjXits4z .image-shape .label,#mermaid-svg-CGs7sqBjbjXits4z .icon-shape .label{text-anchor:middle;}#mermaid-svg-CGs7sqBjbjXits4z .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-CGs7sqBjbjXits4z .rough-node .label,#mermaid-svg-CGs7sqBjbjXits4z .node .label,#mermaid-svg-CGs7sqBjbjXits4z .image-shape .label,#mermaid-svg-CGs7sqBjbjXits4z .icon-shape .label{text-align:center;}#mermaid-svg-CGs7sqBjbjXits4z .node.clickable{cursor:pointer;}#mermaid-svg-CGs7sqBjbjXits4z .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-CGs7sqBjbjXits4z .arrowheadPath{fill:#333333;}#mermaid-svg-CGs7sqBjbjXits4z .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CGs7sqBjbjXits4z .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CGs7sqBjbjXits4z .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CGs7sqBjbjXits4z .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-CGs7sqBjbjXits4z .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CGs7sqBjbjXits4z .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-CGs7sqBjbjXits4z .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CGs7sqBjbjXits4z .cluster text{fill:#333;}#mermaid-svg-CGs7sqBjbjXits4z .cluster span{color:#333;}#mermaid-svg-CGs7sqBjbjXits4z div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CGs7sqBjbjXits4z .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-CGs7sqBjbjXits4z rect.text{fill:none;stroke-width:0;}#mermaid-svg-CGs7sqBjbjXits4z .icon-shape,#mermaid-svg-CGs7sqBjbjXits4z .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-CGs7sqBjbjXits4z .icon-shape p,#mermaid-svg-CGs7sqBjbjXits4z .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-CGs7sqBjbjXits4z .icon-shape .label rect,#mermaid-svg-CGs7sqBjbjXits4z .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-CGs7sqBjbjXits4z .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-CGs7sqBjbjXits4z .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-CGs7sqBjbjXits4z :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 阶段三:淘汰旧系统
所有请求
客户端
代理层/API网关
新系统全功能
新数据库
阶段二:逐步替换
灰度规则
灰度规则
其余请求
数据同步
客户端
代理层/API网关
新服务A

(订单)
新服务B

(支付)
旧系统
新数据库
旧数据库
阶段一:拦截与路由
所有请求
客户端
代理层/API网关
旧系统单体


五、适用场景与优缺点分析

✅ 适用场景

场景 描述
系统规模巨大 遗留系统代码量>50万行,模块耦合严重,无法一次性重写
业务不可中断 金融、电商、医疗等核心系统,停机时间窗口极为有限
需要灰度验证 希望新功能先对部分用户开放(如内部员工、白名单用户),逐步验证后再全量
团队希望持续交付 不想阻塞其他业务迭代,可以并行开发新模块,分批上线

🌟 优点

  • 风险可控:将"大爆炸式"重构拆解为多次小规模迁移,每次影响范围有限,即便失败也可快速回滚。
  • 业务零中断 :新旧系统并行,用户无感知,达到平滑过渡
  • 持续交付:允许团队独立、迭代地交付新功能,不会影响其他并行项目的进度。
  • 可逆性:若某个新服务有问题,可快速切回旧系统,回滚成本极低。

⚠️ 缺点

  • 架构复杂度提升:需维护新旧两套系统、路由逻辑、数据一致性,增加了运维和监控难度。
  • 迁移周期长:大型系统改造可能持续数月甚至数年,对团队耐心和资源是长期考验。
  • 数据一致性挑战:新旧系统可能操作同一份数据,必须处理好双向同步或最终一致性。
  • 团队技能要求高:同时维护旧技术栈和新技术栈,需要团队具备跨技术栈能力。

六、技术栈与落地实践

🛠️ 推荐技术栈

组件 可选方案
代理层/API网关 Nginx、Spring Cloud Gateway、Kong、Traefik、Amazon API Gateway
灰度路由策略 HTTP Header(如 X-User-Version: v2)、用户ID取模、URI路径前缀
流量镜像 GoReplay、Nginx Mirror模块、Istio 流量镜像
服务发现 Consul、Eureka、Nacos
数据同步 Canal(MySQL binlog同步)、Debezium(CDC)、Kafka
链路追踪 Zipkin、Jaeger、SkyWalking

💡 关键实践要点

  1. 先确定新系统的边界:优先迁移"独立、高内聚、低耦合"的功能模块(如用户认证、商品查询等无状态服务)。
  2. 建立完善的监控和告警:必须实时对比新旧系统的成功率、响应时间、错误率,一旦出现偏差立即回滚。
  3. 数据迁移策略
    • 双写方案:新旧系统同时写入,保证数据最终一致。
    • 异步同步:通过CDC(Change Data Capture)将旧系统的变更同步到新库。
    • 只读切换:先迁移"只读"功能,再迁移"写"功能,逐步过渡。
  4. 迭代节奏 :建议每月完成1-2个功能模块的迁移,并设置明确的里程碑。
  5. 充分测试 :利用流量镜像,将线上真实请求复制到新服务,对比响应差异,验证新服务的正确性。

七、与绞杀者模式协同的四大类似模式

在遗留系统现代化改造中,绞杀者模式往往不是孤立使用的,它常与以下模式协同,形成完整的解决方案。
#mermaid-svg-q1OdacmwlpqoRSge{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-q1OdacmwlpqoRSge .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-q1OdacmwlpqoRSge .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-q1OdacmwlpqoRSge .error-icon{fill:#552222;}#mermaid-svg-q1OdacmwlpqoRSge .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-q1OdacmwlpqoRSge .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-q1OdacmwlpqoRSge .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-q1OdacmwlpqoRSge .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-q1OdacmwlpqoRSge .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-q1OdacmwlpqoRSge .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-q1OdacmwlpqoRSge .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-q1OdacmwlpqoRSge .marker{fill:#333333;stroke:#333333;}#mermaid-svg-q1OdacmwlpqoRSge .marker.cross{stroke:#333333;}#mermaid-svg-q1OdacmwlpqoRSge svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-q1OdacmwlpqoRSge p{margin:0;}#mermaid-svg-q1OdacmwlpqoRSge .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-q1OdacmwlpqoRSge .cluster-label text{fill:#333;}#mermaid-svg-q1OdacmwlpqoRSge .cluster-label span{color:#333;}#mermaid-svg-q1OdacmwlpqoRSge .cluster-label span p{background-color:transparent;}#mermaid-svg-q1OdacmwlpqoRSge .label text,#mermaid-svg-q1OdacmwlpqoRSge span{fill:#333;color:#333;}#mermaid-svg-q1OdacmwlpqoRSge .node rect,#mermaid-svg-q1OdacmwlpqoRSge .node circle,#mermaid-svg-q1OdacmwlpqoRSge .node ellipse,#mermaid-svg-q1OdacmwlpqoRSge .node polygon,#mermaid-svg-q1OdacmwlpqoRSge .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-q1OdacmwlpqoRSge .rough-node .label text,#mermaid-svg-q1OdacmwlpqoRSge .node .label text,#mermaid-svg-q1OdacmwlpqoRSge .image-shape .label,#mermaid-svg-q1OdacmwlpqoRSge .icon-shape .label{text-anchor:middle;}#mermaid-svg-q1OdacmwlpqoRSge .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-q1OdacmwlpqoRSge .rough-node .label,#mermaid-svg-q1OdacmwlpqoRSge .node .label,#mermaid-svg-q1OdacmwlpqoRSge .image-shape .label,#mermaid-svg-q1OdacmwlpqoRSge .icon-shape .label{text-align:center;}#mermaid-svg-q1OdacmwlpqoRSge .node.clickable{cursor:pointer;}#mermaid-svg-q1OdacmwlpqoRSge .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-q1OdacmwlpqoRSge .arrowheadPath{fill:#333333;}#mermaid-svg-q1OdacmwlpqoRSge .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-q1OdacmwlpqoRSge .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-q1OdacmwlpqoRSge .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q1OdacmwlpqoRSge .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-q1OdacmwlpqoRSge .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q1OdacmwlpqoRSge .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-q1OdacmwlpqoRSge .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-q1OdacmwlpqoRSge .cluster text{fill:#333;}#mermaid-svg-q1OdacmwlpqoRSge .cluster span{color:#333;}#mermaid-svg-q1OdacmwlpqoRSge div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-q1OdacmwlpqoRSge .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-q1OdacmwlpqoRSge rect.text{fill:none;stroke-width:0;}#mermaid-svg-q1OdacmwlpqoRSge .icon-shape,#mermaid-svg-q1OdacmwlpqoRSge .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-q1OdacmwlpqoRSge .icon-shape p,#mermaid-svg-q1OdacmwlpqoRSge .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-q1OdacmwlpqoRSge .icon-shape .label rect,#mermaid-svg-q1OdacmwlpqoRSge .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-q1OdacmwlpqoRSge .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-q1OdacmwlpqoRSge .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-q1OdacmwlpqoRSge :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 模式生态
绞杀者模式
防腐层 ACL
修缮者模式
分支与抽象
事件拦截/CDC
保护新领域纯净
局部优化旧系统
代码层面切换
数据同步一致性

1. 防腐层(Anti-Corruption Layer, ACL)

核心思想 :在新旧系统之间建立一个翻译层 ,将旧系统的数据模型、接口协议转换为新系统期望的模型,从而隔离旧系统的"坏味道" ,保护新系统的领域纯净。

与绞杀者模式的关系协同关系。在绞杀者模式的第二阶段,新服务往往需要调用旧系统的某些功能或数据,此时ACL作为"缓冲区",避免新系统被旧系统的设计污染。

2. 修缮者模式(Modify/Rejuvenate)

核心思想 :对旧系统进行小步快跑式的局部优化,比如重构一个类、优化SQL索引、升级一个依赖库,而非大规模替换。

与绞杀者模式的关系互补关系。修缮者适用于旧系统还"有的救"的情况(如架构清晰但局部代码腐化),而绞杀者适用于系统已经"病入膏肓"需要整体替换的场景。两者可结合使用------先修缮,再逐步绞杀。

3. 分支与抽象模式(Branch by Abstraction)

核心思想 :在代码中创建抽象层,新旧实现并存,通过配置开关(Feature Flag)在运行时动态切换。

与绞杀者模式的关系更细粒度的版本 。绞杀者模式是在系统级别 进行替换(模块/服务粒度),而分支与抽象是在代码级别(类/方法粒度)进行替换。两者常结合使用,尤其在替换核心组件时。

4. 事件拦截与CDC(Change Data Capture)

核心思想:拦截旧系统的数据变更操作(INSERT/UPDATE/DELETE),将这些变更作为事件流(如Kafka)同步到新系统,保持数据一致性。

与绞杀者模式的关系数据层面的协同。这是解决绞杀者模式中"数据同步"难题的核心技术,确保新旧系统操作同一份数据时不会产生冲突,最终达到一致性。


八、实战案例:电商平台支付系统重构

某电商平台有一个运行了8年的支付单体应用,代码量超过80万行,支付链路长、改动风险大。团队决定采用绞杀者模式进行重构,分为五步走:
#mermaid-svg-dnnYaIausgOj9c7R{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dnnYaIausgOj9c7R .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dnnYaIausgOj9c7R .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dnnYaIausgOj9c7R .error-icon{fill:#552222;}#mermaid-svg-dnnYaIausgOj9c7R .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dnnYaIausgOj9c7R .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dnnYaIausgOj9c7R .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dnnYaIausgOj9c7R .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dnnYaIausgOj9c7R .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dnnYaIausgOj9c7R .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dnnYaIausgOj9c7R .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dnnYaIausgOj9c7R .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dnnYaIausgOj9c7R .marker.cross{stroke:#333333;}#mermaid-svg-dnnYaIausgOj9c7R svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dnnYaIausgOj9c7R p{margin:0;}#mermaid-svg-dnnYaIausgOj9c7R .mermaid-main-font{font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-dnnYaIausgOj9c7R .exclude-range{fill:#eeeeee;}#mermaid-svg-dnnYaIausgOj9c7R .section{stroke:none;opacity:0.2;}#mermaid-svg-dnnYaIausgOj9c7R .section0{fill:rgba(102, 102, 255, 0.49);}#mermaid-svg-dnnYaIausgOj9c7R .section2{fill:#fff400;}#mermaid-svg-dnnYaIausgOj9c7R .section1,#mermaid-svg-dnnYaIausgOj9c7R .section3{fill:white;opacity:0.2;}#mermaid-svg-dnnYaIausgOj9c7R .sectionTitle0{fill:#333;}#mermaid-svg-dnnYaIausgOj9c7R .sectionTitle1{fill:#333;}#mermaid-svg-dnnYaIausgOj9c7R .sectionTitle2{fill:#333;}#mermaid-svg-dnnYaIausgOj9c7R .sectionTitle3{fill:#333;}#mermaid-svg-dnnYaIausgOj9c7R .sectionTitle{text-anchor:start;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-dnnYaIausgOj9c7R .grid .tick{stroke:lightgrey;opacity:0.8;shape-rendering:crispEdges;}#mermaid-svg-dnnYaIausgOj9c7R .grid .tick text{font-family:"trebuchet ms",verdana,arial,sans-serif;fill:#333;}#mermaid-svg-dnnYaIausgOj9c7R .grid path{stroke-width:0;}#mermaid-svg-dnnYaIausgOj9c7R .today{fill:none;stroke:red;stroke-width:2px;}#mermaid-svg-dnnYaIausgOj9c7R .task{stroke-width:2;}#mermaid-svg-dnnYaIausgOj9c7R .taskText{text-anchor:middle;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutsideRight{fill:black;text-anchor:start;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutsideLeft{fill:black;text-anchor:end;}#mermaid-svg-dnnYaIausgOj9c7R .task.clickable{cursor:pointer;}#mermaid-svg-dnnYaIausgOj9c7R .taskText.clickable{cursor:pointer;fill:#003163!important;font-weight:bold;}#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163!important;font-weight:bold;}#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163!important;font-weight:bold;}#mermaid-svg-dnnYaIausgOj9c7R .taskText0,#mermaid-svg-dnnYaIausgOj9c7R .taskText1,#mermaid-svg-dnnYaIausgOj9c7R .taskText2,#mermaid-svg-dnnYaIausgOj9c7R .taskText3{fill:white;}#mermaid-svg-dnnYaIausgOj9c7R .task0,#mermaid-svg-dnnYaIausgOj9c7R .task1,#mermaid-svg-dnnYaIausgOj9c7R .task2,#mermaid-svg-dnnYaIausgOj9c7R .task3{fill:#8a90dd;stroke:#534fbc;}#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutside0,#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutside2{fill:black;}#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutside1,#mermaid-svg-dnnYaIausgOj9c7R .taskTextOutside3{fill:black;}#mermaid-svg-dnnYaIausgOj9c7R .active0,#mermaid-svg-dnnYaIausgOj9c7R .active1,#mermaid-svg-dnnYaIausgOj9c7R .active2,#mermaid-svg-dnnYaIausgOj9c7R .active3{fill:#bfc7ff;stroke:#534fbc;}#mermaid-svg-dnnYaIausgOj9c7R .activeText0,#mermaid-svg-dnnYaIausgOj9c7R .activeText1,#mermaid-svg-dnnYaIausgOj9c7R .activeText2,#mermaid-svg-dnnYaIausgOj9c7R .activeText3{fill:black!important;}#mermaid-svg-dnnYaIausgOj9c7R .done0,#mermaid-svg-dnnYaIausgOj9c7R .done1,#mermaid-svg-dnnYaIausgOj9c7R .done2,#mermaid-svg-dnnYaIausgOj9c7R .done3{stroke:grey;fill:lightgrey;stroke-width:2;}#mermaid-svg-dnnYaIausgOj9c7R .doneText0,#mermaid-svg-dnnYaIausgOj9c7R .doneText1,#mermaid-svg-dnnYaIausgOj9c7R .doneText2,#mermaid-svg-dnnYaIausgOj9c7R .doneText3{fill:black!important;}#mermaid-svg-dnnYaIausgOj9c7R .doneText0.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneText0.taskTextOutsideRight,#mermaid-svg-dnnYaIausgOj9c7R .doneText1.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneText1.taskTextOutsideRight,#mermaid-svg-dnnYaIausgOj9c7R .doneText2.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneText2.taskTextOutsideRight,#mermaid-svg-dnnYaIausgOj9c7R .doneText3.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneText3.taskTextOutsideRight{fill:black!important;}#mermaid-svg-dnnYaIausgOj9c7R .crit0,#mermaid-svg-dnnYaIausgOj9c7R .crit1,#mermaid-svg-dnnYaIausgOj9c7R .crit2,#mermaid-svg-dnnYaIausgOj9c7R .crit3{stroke:#ff8888;fill:red;stroke-width:2;}#mermaid-svg-dnnYaIausgOj9c7R .activeCrit0,#mermaid-svg-dnnYaIausgOj9c7R .activeCrit1,#mermaid-svg-dnnYaIausgOj9c7R .activeCrit2,#mermaid-svg-dnnYaIausgOj9c7R .activeCrit3{stroke:#ff8888;fill:#bfc7ff;stroke-width:2;}#mermaid-svg-dnnYaIausgOj9c7R .doneCrit0,#mermaid-svg-dnnYaIausgOj9c7R .doneCrit1,#mermaid-svg-dnnYaIausgOj9c7R .doneCrit2,#mermaid-svg-dnnYaIausgOj9c7R .doneCrit3{stroke:#ff8888;fill:lightgrey;stroke-width:2;cursor:pointer;shape-rendering:crispEdges;}#mermaid-svg-dnnYaIausgOj9c7R .milestone{transform:rotate(45deg) scale(0.8,0.8);}#mermaid-svg-dnnYaIausgOj9c7R .milestoneText{font-style:italic;}#mermaid-svg-dnnYaIausgOj9c7R .doneCritText0,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText1,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText2,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText3{fill:black!important;}#mermaid-svg-dnnYaIausgOj9c7R .doneCritText0.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText0.taskTextOutsideRight,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText1.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText1.taskTextOutsideRight,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText2.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText2.taskTextOutsideRight,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText3.taskTextOutsideLeft,#mermaid-svg-dnnYaIausgOj9c7R .doneCritText3.taskTextOutsideRight{fill:black!important;}#mermaid-svg-dnnYaIausgOj9c7R .vert{stroke:navy;}#mermaid-svg-dnnYaIausgOj9c7R .vertText{font-size:15px;text-anchor:middle;fill:navy!important;}#mermaid-svg-dnnYaIausgOj9c7R .activeCritText0,#mermaid-svg-dnnYaIausgOj9c7R .activeCritText1,#mermaid-svg-dnnYaIausgOj9c7R .activeCritText2,#mermaid-svg-dnnYaIausgOj9c7R .activeCritText3{fill:black!important;}#mermaid-svg-dnnYaIausgOj9c7R .titleText{text-anchor:middle;font-size:18px;fill:#333;font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-dnnYaIausgOj9c7R :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 2025-01-01 2025-02-01 2025-03-01 2025-04-01 2025-05-01 2025-06-01 2025-07-01 2025-08-01 部署API网关 迁移"支付查询"服务 迁移"退款"服务 迁移"支付核心"服务 迁移"支付回调"服务 全量切换+下线旧系统 第一阶段 第二阶段 第三阶段 支付系统绞杀者重构计划(8个月)

  • 第1个月:部署Spring Cloud Gateway作为统一网关,初期100%流量转发至旧系统。
  • 第2个月 :迁移"支付查询"功能(只读),新服务上线,网关根据user_id尾号灰度放量(10%→50%→100%)。
  • 第3个月:迁移"退款"功能,同样灰度切换。旧系统逐步剥离相关功能。
  • 第4-5个月 :迁移最核心的"支付核心"服务(含事务处理),采用双写+异步校验策略,确保数据一致性。
  • 第6个月:迁移"支付回调"服务。
  • 第7个月:所有流量切换至新系统,旧系统流量降至0。观察一周后,下线旧系统。

最终,整个重构过程未发生一次P0级故障,业务零中断,用户无感知。


九、总结:绞杀者模式的终极心法

绞杀者模式的精髓可概括为八字箴言:

增量演进,以旧养新

它不是一种"技术",而是一种组织战略和工程实践。它要求团队具备:

  • 清晰的模块化思维:能合理拆分功能,定义边界。
  • 强大的工程能力:能搭建网关、实现灰度路由、处理数据一致性。
  • 坚定的耐心:大型系统改造可能持续数年,需要团队的持久投入。

🧭 何时选择绞杀者模式?

条件 决策
系统规模>50万行,团队不敢轻易改动 ✅ 强烈推荐
业务停机窗口严格(如金融、医疗) ✅ 推荐
新系统技术栈已确定,团队有足够人力并行开发 ✅ 推荐
系统老旧但功能简单,可快速重写 ❌ 推荐直接"推倒重来"
团队缺乏微服务/API网关经验 ⚠️ 先学习积累,再实施

📚 延伸阅读

  • Martin Fowler 《StranglerFigApplication》(原博文)
  • 《重构:改善既有代码的设计》(第二版)
  • 《领域驱动设计》(DDD)------ 第14章"防腐层"
  • 《Release It!》 ------ 关于系统稳定性的经典

💬 互动话题:你所在团队是否曾使用过绞杀者模式进行系统重构?遇到过哪些坑?欢迎在评论区交流分享!


📌 标签架构设计 绞杀者模式 遗留系统 重构 微服务 API网关 DDD