架构图设计指南:从分层到版本管理,让图真正被看懂
最近在梳理一个遗留系统的重构方案评审会上有人把新架构图投到屏幕上会议室里先是安静了三秒然后就开始吵。有人指着某个方框问这是进程还是容器有人问这两个箭头是调用还是数据流还有人拿着旧图对比发现同一块服务在两张图里画在不同位置。这场面我太熟悉了几乎每个技术团队都经历过——图是画了但画完没人看得懂。做 diagram-design 这件事本质上不是画图而是设计沟通载体。图从诞生那刻起就是给人看的它要回答读者的疑问系统分几块依赖怎么走哪里是边界数据往哪流如果图回答不了这些问题那它就只是墙纸。这篇内容我打算把过去几年画架构图、评审架构图、以及给团队定绘图规范时积累的东西拆开讲包括图层怎么分、符号怎么定、颜色怎么用、以及最要命的——图怎么才能不被扔进仓库吃灰。适合带团队的技术负责人、做方案设计的开发同学还有刚入行需要学会画一张能过关的图的新人。1. 为什么优秀的架构图这么少先认清图纸和代码的本质差异1.1 代码解决的是机器的校验问题图解决的是人的认知问题很多开发同学画图画不好根子不在工具也不在审美而在思维方式。我们写代码写惯了脑子里天然带着线性执行和编译校验这套逻辑。代码有语法检查有类型系统写错了编译器会报错改坏了测试会翻车。但图没有这些——图是画布上的一堆矩形和箭头没有任何东西会在你画错的时候弹窗警告。所以画图的第一性原理是你不是在画系统写真你是在画认知地图。这跟城市地铁图是一个道理。地铁图并不按真实地理比例尺画它突出的是站与站之间的先后关系、换乘关系、线路归属。没有哪个乘客会拿地铁图去丈量公里数乘客要的是怎么从这站到那站。架构图也一样它的服务对象是人的大脑不是机器。我经常跟团队说一句话写代码的时候你的甲方是编译器画图的时候你的甲方是十天后的你自己。一张图如果放十天再拿回来看自己都认不出那几个菱形是什么意思那这张图的信息密度就是零。代码的精确性来自语法系统图的精确性来自作者自己设定的符号体系——这就是为什么画图必须立规矩后面我会专门讲符号规范。1.2 一张好图的三个验收标准我评审架构图时的习惯判据如果你问我作为评审人怎样快速判断一张架构图是好图还是废图我会用三个标准过一遍。第一是可读性。把图递给一个没有参与项目的同事让他只看十秒然后说出这张图在讲什么。说不出来就是不合格。这条标准能过滤掉八成自嗨型架构图。我发现一个规律新手画图特别喜欢把能想到的模块全画上去美其名曰完整结果图面信息密度爆炸主链路淹没在支线里谁看谁晕。可读性的本质是有主次一眼扫过去能立刻抓住主干。第二是准确性。图里的每个矩形、每个箭头都必须有明确的语义并且和真实系统对得上。比如箭头到底是接口调用异步消息还是数据落盘必须一一对应不能一个箭头表示三种关系。我见过团队画的图一个大框里面写xxx中间件下面拉了三根线一根连数据库一根连接口至于中间件具体起了什么作用图上完全无法验证。这种图的危害比没有图更大因为它让人误以为自己理解了系统。第三是可演进性。图的维护成本要低改一处服务拆分不用重画半小时。这点直接决定了图会不会死。我会问如果这个月我们把消息队列从A换成B画图的人需要动几个元素答案是越少越好。那些用纯绘图工具手摆节点、画一个体系要一个下午的图基本死得都很快因为没人愿意维护。可演进性还有一个隐藏要求图源文件必须能进版本管理能被diff能追历史。后面第五部分我会展开讲这个。2. 分层而不是分好坏业务图、系统图与部署图各画各的2.1 先回答四个问题再决定画哪一层几乎每个团队都有一张万能架构图恨不得把所有信息都塞进去。结果就是不同角色的读者各取所需谁也没法完整使用。解决这个问题的办法不是画得更细而是分层——把架构图按视角拆成业务层、系统层和部署层每层为特定读者服务。动手画图之前先停下来问自己四个问题。第一个问题谁看这张图业务方看的图重点是角色、流程、规则开发看的图重点是模块、依赖、接口运维看的图重点是服务、资源、网络。读者决定抽象层级这永远是第一优先级的决策。第二个问题读者看了这张图之后要做什么决策业务方可能是确认流程顺不顺开发可能是确认拆几个服务、依赖方向对不对运维可能是确认扩容点在哪儿。图的存在意义是帮读者做决策不是帮读者了解一切。第三个问题哪些关系是这张图必须表达的核心关系选最重要的两三种关系画出来比如调用关系和数据落盘其他一律省略。一张图表达的关系类型越杂理解成本就越高。第四个问题哪些细节可以下沉到下一张图比如系统层的图里某个服务内部的类结构、表结构完全不用画那是应用层图的事。画图的时候心里要有一条原则图是分层的一层画不下所有细节也不应该画下所有细节。2.2 用订单系统的例子拆解三个层次各自的信息边界拿大多数团队都有的订单系统来举例三个层次画出来的东西截然不同信息边界非常清晰。业务架构图面向的是产品经理和业务方。这张图上画的是角色和规则用户发起订单、支付系统确认收款、库存系统扣减库存、配送系统安排发货以及超时未支付自动取消这条规则。它不需要出现任何技术名词模块名字要写成订单发起支付确认库存扣减这种业务动作不写OrderService和Redis Lua脚本。业务架构图回答的是业务流程通不通。系统架构图面向的是服务端开发。这张图才出现 OrderService、PaymentClient、InventoryService、MQ 等具体的服务模块箭头表达的是接口调用关系和异步消息关系图中必须能看出订单创建成功后通过消息触发库存扣减这条链路。系统架构图回答的是模块依赖合理不合理、有没有循环调用、故障会不会顺着调用链传播。部署架构图面向的是运维和SRE。这张图画的是服务跑在什么环境上几个实例挂在哪个网关后面数据库是主从还是分片Redis 是集群还是哨兵日志往哪个采集端送。它回答的是扩容在哪儿扩、故障在哪儿断、流量怎么进。这里有个团队里非常常见的通病把三层画在同一张图上。图形上表现为——业务动作和内部服务出现在一起逻辑节点和物理节点都画成一样的方框。读者看到这种图大脑会强制切换视角一会儿理解业务一会儿理解技术来回切换几次就放弃了。所以我强烈建议一张图只干一件事。分三张图画每张图都有明确读者反而比一张大全图更受欢迎。3. 布局、形状、颜色与命名一张图让人十秒看懂的设计规范3.1 方向、边界与箭头语义先于美观很多人画图栽在符号语义混乱上。先定一个大原则图里每个元素的形状、边框、颜色都必须代表一个固定语义全图保持一致。语义一旦定了就别因为这个模块想突出一下而随意改动。先看方向。全图的主流程必须统一方向要么从左到右要么从上到下。从右到左或者从下到上的回流路径要画成明显的支线不能和主流程混在一起。主从左到右返回路径就走下方回折这也是阅读习惯决定的——人的视线天然从左往右扫你把调用方向画反读者得顺时针绕图一圈才能理清链路。再看边界。容器的边框要能表达归属关系。比如一个服务内部的多个组件必须用一个外框包起来外框上标注服务名内部才是组件节点。外部系统用另一种样式表示比如粗边框或者不同的底色让读者一眼识别这个东西不归我们管。边界画清楚了图的上下文就清楚了。箭头是架构图里最重要的元素也是最容易被乱用的。我建议图例里至少区分三种箭头实线箭头表示同步调用虚线箭头表示异步消息带实心圆点的连线表示数据落盘或读取。箭头旁边不要只图省事写调用两个字最好把接口名或消息主题标注出来比如POST /api/v1/orders或topic: order.created。这里也要强调一个反向情感别画双向箭头。双向箭头表面上省了一条线实际上把谁发起、谁响应的关键信息抹掉了排查调用链时特别误事。3.2 颜色和密度的极简原则视觉装饰是维护成本颜色在架构图里是语义工具不是装饰工具。我见过有人用八种颜色给每个模块上色理由是好看结果一张图花里胡哨读者根本分不清颜色的含义。我的规范是一张图最多三种语义色比如主链路用一种色故障/风险路径用一种色外部系统用灰色统一处理。其余元素全部用默认底色的黑白线框。颜色一旦承担语义就不能随便改否则维护的人会疯掉。密度控制同样重要。认知心理学里有个7±2法则人脑工作记忆能同时处理的组块数量有限。我把它延伸到架构图上一个容器框里能直观扫出来的节点别超过7个超过7个就说明这一层抽象错了——要么该继续分组要么该拆成子图。节点文字也尽量压缩一个节点一行字标注只用服务名关键接口别把配置参数、KV列表全塞进去那些细节放文档里。还有间距问题。节点之间的留白不是浪费而是给读者分块的空间。间距过小会让所有元素黏成一坨难以分组阅读间距拉大到足以看清边界就够了。我画完图有个固定动作整体缩小到50%再缩略看一眼如果缩略后还能分清模块边界这张图的间距才是健康的。3.3 命名与图例跨团队协作时的隐形沟通成本图画的读者往往不只是自己团队还有上下游团队。此时命名的口径一致性就凸显出来了。同一个服务代码里叫 order-service你们团队内部叫订单中台图上又写订单域服务三个名字来回换别的团队根本对不上号。我的建议是一切以代码仓库名为准。图上凡是能对应到真实服务/数据库/消息主题的节点命名必须和代码仓库、配置文件里的名字完全一致最多在后面加括号写中文名。图例不是可选项是跨团队架构图的必需品。图例要声明的内容包括每种线型的含义、每种颜色的含义、容器边界的含义、以及这张图对应的代码版本或更新日期。我通常会要求在图右下的角落固定放一块图例版本信息哪怕只是一个文本标注也能避免这图是不是过期了这种灵魂拷问。跨团队协作时我还有一个实际体验同一个术语在不同团队里意思可能完全不同。比如服务A调用服务B在有些团队语境里包含RPC同步调用在另一些团队里专指HTTP接口。所以在图例里加一行调用同步RPC/HTTP这样的描述看起来啰嗦实际上能省掉很多合作时的扯皮时间。4. 从草稿到成品的绘制流程先关系后布局先黑白后加彩4.1 第一步用文本把实体和关系写清楚我画图的习惯和别人不太一样第一步是不打开绘图工具的。我会先把要表达的信息用纯文本列出来格式很简单就是一张关系清单。比如要画订单系统架构图我会先写参与者用户、运营后台服务OrderService、InventoryService、PaymentClient、DispatchClient存储订单库、Redis订单状态缓存关键链路用户创建一个订单 - 订单库写入 - 发消息扣库存 - 支付回调更新状态外部系统支付网关、配送开放平台风险点库存扣减失败需要补偿图里要标出这条异常分支这份清单就是图的源代码。它的作用是强迫你在画线之前先想清楚到底有哪些实体哪些关系是主干哪些是支线。我见过很多同学直接开工具画了删删了画一个小时过去了图和初始想法一样混沌——就是因为没有这一步文本梳理。文本写法跟代码里先写接口定义再写实现是同一个道理先定契约再画视图。4.2 第二步到第四步草图优化与视觉规范的具体手法关系清单理完之后我才会开白板工具画草图。草图阶段只看关系和布局完全不管配色和样式。具体操作就是先按主链路顺序把节点从左到右或从上到下排开然后把清单里标出的异常分支、外部系统、存储节点放在主链路两侧。布局的核心目标是交叉线最少。两条线交叉一次读者还能反应交叉三次以上基本就是要重画了。减少交叉的办法就是把一些边绕个大弯或者把相关节点聚成一组再连线。草图满意后再进第三步加容器边界。把归属同一服务的节点用外框包起来外部系统放到边界线的外侧或底部区域。这一步做完图的层次就出来了——读者能直观看到哪些东西在我掌控内哪些东西在外面。第四步才是上视觉规范上色、定字体、拉间距。给主链路加语义色给外部系统加灰底色把文字大小统一成两级——一级是容器/服务名二级是节点名和接口名。第四步和第三步之间有一个重要的中间检查在加颜色之前先把黑白版截图发给一个不懂项目的同事看问一句大概讲了什么。黑白版能通过可读性测试再上色才有意义。因为颜色是辅助信息如果去掉颜色这张图就废了那说明结构本身有问题靠颜色救不回来。4.3 工具选型的真实取舍按图的生命周期选择载体工具选型是我见过团队纠结最多的地方其实没那么复杂按这张图的生命周期来选就行。第一种是临时讨论图。比如方案评审会上现场画的草图生命周期只有一场会议。这种图用白板工具快速画讲究的是快和够用画完拍照归档就完成了不值得投入精致度。第二种是沉淀型架构图。生命周期以月计要给多个团队反复看甚至进文档、上墙。这种图需要精细布局、规范符号、清爽配色适合用矢量绘图类工具精雕细琢。但我必须提个醒尽量少用纯鼠标拖拽型工具画这种图因为后续维护的人要花大量时间对版本、挪位置、改线形改一次半小时起步。第三种是代码仓库里的活图。这是我最推荐用于核心架构的形态——用纯文本描述语言来定义图再渲染成图形。这种方案的好处是图源文件就是几行文本天然能进版本管理能diff、能review、能pin到某个代码版本上接口变了顺带改一行文字就行。团队里经常有人说架构图老是过期用这种活图机制就是我能找到的最优解。在把架构图当作工程资产而不是一次性画布的团队里这种文本即图的做法可以算一劳永逸。具体选哪种取决于这张图的维护频度——维护频度越高越该往文本化、版本化的方向走。5. 架构图的死亡方式与续命方案给图做版本管理5.1 图与代码的漂移无人维护的架构图比没有图更糟架构图最常见的死因不是画得丑而是过期。我用图与代码漂移这个词来形容这个现象代码每天都在变架构图却是某个时点的快照过了几个月就和真实系统对不上了。这时候如果有人拿旧图排查线上问题照着图里的服务名和拓扑去找结果发现服务早就拆了链路早就改了——不仅浪费半小时还会让整个团队对架构图失去信任。更可怕的是团队一旦失去对图的信任后续就没人愿意画图也没人愿意看图系统知识就全散落在个人脑子里了。防止漂移的第一道防线就是把图当成代码来管理。凡是最终进文档、进wiki、上墙的正式架构图必须同时附带一个可编辑的源文件并且放进版本管理仓库——绝不能只放一张导出的PNG。只有PNG的话后人想改就只能重画重画一次就劝退一个人图自然就死了。第二道防线是建立图片更新触发机制。比如每次做技术方案设计时把更新受影响架构图作为验收清单里的一项或者代码里某个核心模块发生变化时PR描述里必须写明对应架构图是否过时——不更新图就不予合并。看起来严格但坚持一年之后团队的图基本上就处于和代码同步漂移的健康状态了。5.2 常见坑位清单评审架构图时我每次都会踩到的地方下面这几个坑是我这些年评审团队内部架构图时反复见过的列出来给大家避雷。第一坑一张图混入多个抽象层次。容器和代码类画在一起逻辑节点和物理节点同样式。这个问题我在第一部分反复提过但每次评审还是会遇到。原因很简单分层图要求画的人先想清楚读者而很多人开画之前根本没做这一步。解决办法就是开头那四个问题动手前必须过一遍。第二坑箭头语义不标。图上画了十几根线全部只有箭头没有标注你说它是调用也行说它是消息也行说它是数据流也行。箭头没语义等于没画。排查问题的时候谁也不知道这根线上实际跑的是什么协议最后还是要回到代码里去翻。第三坑只画理想态不标当前态。很多架构图画的是重构完成后的样子但现实是重构还在灰度阶段半边旧系统半边新系统。图里不标出灰度区域读者以为全部切换了一排查发现还在走旧逻辑。正确的做法是在图上明确标出已切换灰度中待下线三种状态哪怕只是加个颜色点。第四坑循环依赖被画没了。代码里有循环调用是个问题但架构图里经常看不到——因为画图的人潜意识会回避交叉硬生生把A调用B、B调用A画成两根平行线放在图的两端看着不交叉掩盖了循环。我的做法是如果系统存在循环调用架构图必须用醒目的方式标出来比如用风险色加粗。图是暴露问题的不是掩盖问题的。第五坑过度装饰。有些图为了美观加了阴影、圆角、渐变、图标好看是好看了但改一次图要折腾半小时。装饰性元素不携带语义徒增维护成本。我一直和团队说架构图的美应该来自清晰的结构和克制的配色不来自Photoshop级别的装饰。5.3 协作时的冲突解法与个人维护习惯多人维护同一张架构图最大的问题是互相覆盖。尤其在矢量绘图工具里A同学挪了服务位置B同学在那拖了个新节点保存完整个布局乱了。我推荐的解法分两种情况。如果图的版本管理做得好团队直接用文本化方案协作多人改图就是改文本冲突交给版本管理工具处理review的时候一行行diff下来谁改了什么都清清楚楚。这是我认为的最优路径唯一的门槛是画图的人要学一点文本语法但那个学习成本比起反复重画图的成本低得可以忽略。如果团队暂时还离不开可视化工具那就约定区域负责制每块区域的节点管理员固定一个人其他人想改必须通过管理员或者至少基于管理员的最新版本在自己分支上改。没有这个约定多人同时开一张图一定会破坏布局。我见过的最痛苦场景就是两个人花了一下午把一张架构图排得整整齐齐第二天打开发现另一个同事导入了旧版本存档整个下午白干了。我个人的习惯是图不求一次完美但求每次变更都顺手。一个模块的文本描述改了顺手更新图源文件里的一行字整个过程不超过十秒这才是架构图能长期活着的关键。那些画一张图花一整天、之后一年不碰一次的图本质上只是给汇报用的装饰品不是工程资产。最后分享一个我自己坚持了很久的小技巧每张正式架构图的右下角永远留一行小字记录最后更新日期 更新的PR编号。这一行字就是这张图的生命线。看到这张图的人能立刻确认它的时效性维护它的人也能顺着PR编号快速了解到底改了什么。这个习惯看上去简单却是我见过的所有图纸管理经验里性价比最高的一个。