一个生命科学领域的SaaS平台,在监管最严的行业里,用3年时间把一座代码巨兽拆成了17个独立服务。整个过程中,他们的生产环境从未停服超过30分钟。

这不是技术团队的自嗨。PraxisPro的工程师们最近公开了完整复盘,里面有个细节很有意思:他们本可以抄近路,却主动选了最难走的那条。

巨兽的代价:一次改一行代码,要部署整个系统

PraxisPro的早期架构和所有创业公司一样——一个单体应用(monolith,单一巨型代码库),一个数据库,一键部署。创始人坦言,这在起步阶段是正确选择,"当你的最大问题是验证有没有人要你的产品时,单体架构完全够用"。

但产品活了,麻烦就来了。

发布变成高危动作。哪怕只改一行会话管理的代码,也得把整个应用重新部署一遍——RAG层、报表服务、所有模块打包上线。万一这行代码有问题,全站一起挂。

代码边界彻底模糊。会话、用户、对话、报表的逻辑全挤在一个仓库里。工程师想加个报表功能,得先啃完不相干的用户管理代码,生怕踩到雷。

扩容更是冤大头。某个功能流量暴涨,只能把整个系统一起扩容。90%的模块在摸鱼,账单却按峰值全额收取。

最要命的是幽灵回归。A角落的改动,两周后在Z模块炸雷。在生命科学这种监管行业,数据完整性和系统可靠性不是加分项,是生死线。

他们算过一笔账:每次全量发布,平均需要4小时准备,2小时回滚窗口,工程师精神高度紧张。一年下来,直接工时损失超过600人时。

两条路摆在面前:大爆炸还是零敲碎打

两条路摆在面前:大爆炸还是零敲碎打

团队清楚必须拆,但怎么拆?

方案A是"大爆炸重写"——冻结功能,全员投入,6个月后焕然新生。这个方案在PPT上很漂亮,现实中几乎必死。他们的客户正在生产环境跑关键业务流程,停服一天就是违约。

方案B是"绞杀者模式"(Strangler Fig Pattern,像绞杀植物一样逐步替换旧系统)——新服务边建边切,老系统边缩边退。慢,但业务不中断。

PraxisPro选了B。不是因为他们喜欢自虐,而是算过一笔账:大爆炸重写的隐性成本,通常比预期高3-5倍。而他们的监管客户,一次超过30分钟的计划外停机,就可能触发审计。

第一个被拆出来的是用户认证服务。理由很务实:边界清晰,调用频繁,出问题了也容易回滚

他们用API网关做流量调度,新请求走新服务,老请求维持原状。两周后,认证服务的流量100%切完,老代码里的相关模块标记为废弃。不是删除,是冻结——"我们学会了对历史代码保持敬畏,删一行可能触发连锁反应"。

最反直觉的决策:故意保留技术债

最反直觉的决策:故意保留技术债

迁移过程中,团队做了个让外人困惑的决定。

有些模块明明可以一起重写,他们故意留着不动。比如一个用了7年的报表生成器,代码丑陋,性能一般,但运行稳定。团队评估后决定:只封装API,不碰内部逻辑。

「我们的目标不是代码漂亮,是风险可控。」技术负责人解释,「那个报表模块每年被审计两次,监管文档堆了半米厚。重写它意味着重新走一遍验证流程,6个月起步。」

这个决策省下的时间,被投入到真正卡脖子的环节:数据管道和合规审计追踪。前者决定了新架构能不能扛住客户的数据洪峰,后者决定了能不能过得了FDA(美国食品药品监督管理局)的检查。

3年下来,17个服务上线,单体代码量从40万行降到8万行。但那个报表生成器还在,现在是个黑盒API,外面包着新的监控和熔断机制。

团队内部有个说法:技术债就像房贷,关键不是有没有,而是利率多少、现金流能不能覆盖。有些债,按时付息比提前还清更划算。

迁移完成后的意外发现

迁移完成后的意外发现

新架构跑稳后,一些当初没预料到的变化出现了。

发布频率从两周一次变成一天多次。因为每个服务独立部署,改动范围可控,回滚只需切流量,不用重启整个系统。工程师的精神状态明显改善——"至少周末能睡踏实了"。

故障隔离救了团队好几次。去年一次数据库连接池泄漏,只影响了对话服务,用户认证和报表完全无感知。换作以前,全站崩溃,客服电话被打爆。

但成本结构变了。17个服务意味着17套监控、17份日志流、17组告警规则。运维复杂度不是线性增长,是指数级。他们不得不专门成立平台工程小组,把重复劳动抽象成内部工具。

还有个隐性成本:工程师的认知负荷。新人入职,面对的不是一个代码仓库,是一张服务调用拓扑图。调试问题需要跨多个服务的日志串联,工具链的学习周期拉长了两周。

PraxisPro的复盘文档里有个细节没展开:迁移第三年,他们曾考虑把几个高频调用的服务重新合并,减少网络开销。最终没动手,因为"再折腾一次的政治成本太高"。

这个念头现在还在技术债清单里,优先级是"P5——除非架构师离职,否则不碰"。

他们的最后一个服务——那个最古老的会话管理模块——计划在今年Q4下线。届时,这场持续3年多的迁移才算真正结束。而那个7岁的报表生成器,预计会活到2030年,或者下一次监管框架大改,看哪个先来。

如果你的团队也在拆单体,你会选择保留哪个"丑陋但稳定"的模块不动?