今天去翻公司的 Confluence 维基,本想找一下支付系统的调用拓扑图。结果点开一看,最近一次更新时间竟然定格在两年前。图里的核心中间件早就被改掉了,有些下游接口也早已废弃,而新拆出来的微服务在图上甚至查无此人。

看着这种早已过期的 Visio 框图,心里真是一万只羊驼奔腾而过。这是绝大多数工程团队的通病:图和代码是完全脱节的。新需求一催,大家提了代码就跑,谁还会有闲心去登录绘图网站、调整框图对齐、重新导出图片再贴进 Wiki 页面?

手动绘图的维护成本简直就是灾难。为了根治这个大坑,我们开始推行“架构即代码”(Architecture-as-Code)理念,将 C4 Model 设计规范与 Git 仓库绑定,直接用 Markdown + Mermaid 语法在代码库中书写系统架构图,实现系统设计与代码改动的“同生共死”。

下面是我们项目中实际落地的 C4 Container 级别系统设计图。通过这种文本声明式的定义,任何开发者改动系统链路时,只需要用几行文本就能顺手把架构图修好:

graph TD
    %% 样式定义
    classDef client fill:#D4E6F1,stroke:#2980B9,stroke-width:2px;
    classDef gateway fill:#FADBD8,stroke:#C0392B,stroke-width:2px;
    classDef service fill:#FCF3CF,stroke:#F39C12,stroke-width:2px;
    classDef storage fill:#D1F2EB,stroke:#16A085,stroke-width:2px;

    %% 节点定义
    Client["📱 客户端 App (React Native)"]:::client
    Gateway["🛡️ API 网关 (Kong / Envoy)"]:::gateway
    
    subgraph CoreDomain ["核心后端服务域"]
        OrderService["📦 订单微服务 (NestJS)"]:::service
        PaymentService["💳 支付微服务 (Go / Zap)"]:::service
        AuthService["🔑 认证鉴权中心 (Rust)"]:::service
    end

    Redis["⚡ 分布式缓存 (Redis Cluster)"]:::storage
    MySQL["💾 主业务数据库 (MySQL Cluster)"]:::storage
    MsgQueue["📬 消息队列 (Apache Kafka)"]:::storage

    %% 链路定义
    Client -->|HTTPS / GraphQL| Gateway
    Gateway -->|HTTP / JSON / JWT| AuthService
    Gateway -->|RPC / gRPC| OrderService
    Gateway -->|RPC / gRPC| PaymentService

    OrderService -->|分布式锁 / 查单缓存| Redis
    OrderService -->|事务读写| MySQL
    OrderService -->|发送订单事件| MsgQueue

    PaymentService -->|扣款流水入库| MySQL
    PaymentService -->|发送扣费成功事件| MsgQueue
    MsgQueue -.->|异步消费更新状态| OrderService

    linkStyle default interpolate basis;

把这段文本贴在代码库根目录的 ARCHITECTURE.md 里面,在 VS Code、GitHub 或 GitLab 里都可以开箱即用直观渲染。在提 PR 修改后端链路时,代码变更和 Mermaid 的文本描述必须放在同一个 PR 里过 Code Review。有了 Git 历史提交做背书,再也不用担心“代码改了,文档没改”的扯皮问题。

通过引入 C4 Model 把复杂的系统拆解为 Context(上下文)、Container(容器/服务)、Component(组件)和 Code(代码)四个由粗到细的层次,我们过滤掉了无关的噪音,只专注于服务层级和数据流的走向。

不过,虽然 Mermaid 极其省事,但也有架构师吐槽它的排版机制太黑盒,有时候多画一条线,整张图的布局就会直接崩溃,丑得没法看。

大家在团队中是如何维护架构图的?是继续坚守 Draw.io / Visio,还是引入了像 Structurizr 这种更重度的 Architecture-as-Code 方案?欢迎分享经验。