Skip to content

演进式架构与适应度函数 ​

定位:架构方法论深化系列之二。架构图是快照,系统活在时间里。这篇总结"架构是持续决策过程"的落地方法。内容包括:适应度函数怎么建、增量变更怎么走(绞杀者模式)、架构量子和可演进性怎么度量。

架构不是一次性决策 ​

传统架构观的问题:架构师在项目初期画一张大图,随后进入"维护期"——图过时,人离开,决策理由失传。演进式架构观换一个前提:

  • 架构 = 结构 + 一组受保护的架构特征(性能、安全、可模块化……)+ 持续验证它们的机制。
  • 决策不是一次做对,而是保持每一步都可逆、可验证、低成本地走下一步。是持续的手艺活,不是一次性的雕塑。
  • 演进的敌人往往不是技术而是组织。团队边界与服务边界不对齐,小步演进会淹死在协调成本里(见《康威定律与团队拓扑》)。
  • 与《技术决策与ADR》的关系。ADR 记录"当时为什么这么选",适应度函数负责"选完之后别被人改坏"。一个管决策留痕,一个管决策存活。

一个直接推论:评估架构的标准从"是否最优"变成"能否演进"。能以小步、低风险、可回退的方式变更的架构,赢过任何一张完美但僵硬的大图。

适应度函数:把"重要的东西"变成可执行的检查 ​

定义:对某项架构特征的客观化完整性评估,理想形态是能跑在 CI 里的自动化检查。分类两个正交维度:

分类维度类别含义例子
粒度原子(atomic)单独运行、检验单一特征单接口 P99 延迟断言;循环依赖检查
粒度整体(holistic)联合多项特征整体评估全链路压测下的"容量+一致性"联合判定
主观性客观机器判定,无人类裁量代码覆盖率阈值、依赖规则
主观性主观(含群体评估)人来评,用 checklist 结构化架构评审打分、代码健康度互评

工程上值得建的几类:

性能类     :核心接口 P99 < 200ms(压测流水线断言,超阈值红牌)
稳定性类   :变更后错误率环比涨幅 < x%;资源水位上限
耦合类     :模块依赖方向检查(分层规则、禁止反向依赖,ArchUnit 思想)
代码健康类 :圈复杂度阈值、重复率、热点文件的变更爆炸率
契约类     :调用方契约测试全绿(见《API设计与契约治理》)

关键在自动化 + 阻断性。写在 wiki 里的架构规范等于没有规范。只有出现在 CI 红灯里、挡住合并的适应度函数,才真正参与自然选择。

落地时的三个常见坑:

坑形态解法
指标通胀什么都要测,红灯常年挂,团队学会"忽略红灯"每个域只保护 2-3 个最重要的特征,其余放报表不放 CI
阈值拍脑袋P99 阈值和真实业务毫无关系,误报/漏报都多从线上真实分布取分位数反推,季度校准一次
只测不改红灯挂两周没人修,检查沦为装饰红灯必须在 SLA 内修复,修不动就显式降级并记账为债(见《技术雷达与技术债管理》)

增量变更与绞杀者模式 ​

大爆炸重写是演进式架构的反面。对必须替换的老系统,用绞杀者模式按子域逐步搬迁:

阶段一:搭门面(Facade),流量先不动
   请求 ──> ┌──────────────┐
           │   老系统(整体) │   新系统只旁路复制数据做比对
           └──────────────┘

阶段二:按子域逐个搬迁
   请求 ──> ┌──────────────┐
           │ 门面/路由层    │──子域A──> 新系统A ✅
           │ (按域切流开关) │──子域B──> 新系统B ✅
           └──────┬───────┘──其余──> 老系统(收缩中)
                  │
             (每切一个域,老系统就瘦一圈)

阶段三:老系统归零下线,门面视情况移除
   请求 ──> 新系统A / 新系统B ...

要点:

  • 入口契约不变:对调用方永远呈现同一个门面,搬迁对上游无感,兼容性压力收敛在门面内部。
  • 按业务子域切,不按技术层切:先搬订单读、再搬订单写、最后搬结算。而不是"先换数据库再换应用"这种全量横切。
  • 双跑比对先行:新链路先以影子流量跑数周,比对新旧输出差异,归零后才切真实流量。切流阶梯见《系统切流通用方案》。
  • 同族的增量手法还有扩展-迁移-收缩(并行修改)。新路径上线 → 存量逐步迁到新路径 → 老路径流量归零后删除。本质是绞杀者在"单个行为"粒度上的应用。四层检查点见《系统设计如何全方位考虑兼容性问题》。

绞杀者与两种失败路径的对照:

大爆炸重写绞杀者模式
交付节奏冻结期数月,一次性切换每个子域独立交付,持续见效
风险形态切换日 all-in,失败即回不去每步可回退,爆炸半径限于单子域
需求响应冻结期老系统只修不加,需求积压老系统继续接需求,搬到哪切到哪
常见死法老新并行维护成本压垮团队,砍掉重写门面层无人治理长成新的上帝模块

最后一行是绞杀者自身的坑:门面是临时建筑,迁移完成必须拆或收缩。否则绞杀者老树死了,门面成了新的绞杀者。

架构量子与可演进性度量 ​

架构量子 = 能独立部署、独立产生业务价值的最小单元(及其配套的通信与数据设施)。

  • 单体只有一个量子:任何变更都要整体发布,演进粒度粗。
  • 微服务的价值不在"小",在于把系统切成多个量子:订单域能日级演进,不必拖着结算域一起发版。
  • 判断拆分是否有效就看量子是否真实。一个"服务"若离开别的服务既不能部署也不能验证,它不是量子,只是进程层面的装饰。
单量子(单体):                          多量子(真微服务):

变更 ──> 整体构建 ──> 整体发布            订单域变更 ──> 只发订单服务 ──┐
        (任何小改动                                   结算域不动      │独立演进
         都动全身)                                    └── 互不阻塞,各自按节奏发布
                                                        (假的例外:改一个接口要
                                                         三个服务同版本上线 = 没有量子)

可演进性本身也要度量,候选指标:

指标含义信号
变更提前期代码合并到生产见效的时长越长,量子越假
部署频率单个量子的独立发布次数长期 < 每周一次,说明耦合住了
变更成功率发布后无需回滚/热修的比例低 = 每步并不可逆,演进在赌
适应度函数通过率CI 中架构类检查的红灯频次与修复时长红灯长期挂着 = 债务在复利,见《技术雷达与技术债管理》
可逆性一次变更能多快回退且不丢数据靠灰度与回滚,见《发布工程与灰度体系》

演进的运营节奏 ​

演进不是等"想清楚了"再动,而是固定节拍地小步走:

  • 季度演进规划:从适应度函数的历史数据里找恶化最快的特征,作为下季度演进主题。而不是架构师拍脑袋选感兴趣的。
  • 每个迭代至少一个结构性小改:拆一个模块、消一条反向依赖、还一小笔债。演进停止的架构不是"稳定",是"僵化前夜"。
  • 大改必带退出机制:任何"先共存"的设计(双写、双跑、门面)立项时就写清拆除条件和时间表。与《技术雷达与技术债管理》的淘汰环同思路。
  • 演进决策留痕:拆哪个量子、先搬哪个子域,都属于难回头的结构性决策。按《技术决策与ADR》落记录,避免半年后没人记得"为什么先搬订单"。

可演进性追问链 ​

接手或评审一个架构时,按这条链连问:

1. 这套架构上一次成功的结构性变更花了多久?  -> 一年以上,演进能力存疑
2. 架构的哪些特征是"受保护"的?            -> 列不出来 = 没有适应度函数
3. 这些保护是 CI 阻断还是文档约定?          -> 文档约定等于没有
4. 最小的可独立部署单元是什么?              -> 答不出量子在哪 = 假拆分
5. 老逻辑的退出机制是什么?                  -> 只加不减的架构终将僵死
6. 下一层债务先在哪爆发?                    -> 连不上债务视角 = 演进无排期
7. 门面/双写这些过渡物,拆除条件写在哪?     -> 没写 = 明天的绞杀者是门面自己

一句话总结 ​

把架构当成活的。重要的特征写成适应度函数进 CI。大的变更走绞杀者小口啃。量子划分决定演进粒度,债务与可逆性持续度量。架构师的产出不是一张图,而是一套让系统自己变好的选择压力。

2026-10 新增(架构方法论深化系列)。