
一张架构图改了六版还被评审问“这个箭头到底什么意思”这种尴尬我经历过太多次。后来才明白问题不在画图软件熟不熟练而是从一开始就没有把 diagram-design 当成一件需要“设计”的事来做。图表设计不是把方框和箭头堆在一起它是在用空间关系、视觉层级和连接语义把一套系统的结构逻辑准确传递给别人。这篇文章我会把图表设计的完整思路、工具选型、布局规则和实操踩坑经验一次性讲透适合需要画架构图、流程图、关系图的开发、运维和产品同学参考。1. 图纸不是画出来的是先设计出来的1.1 一张烂图毁掉一次评审我举一个特别常见的场景。你花半小时在画布上拖出一张系统架构图服务命名了、连线也拉了、数据库也画了自我感觉挺完整。结果评审会上产品问“这条线是同步调用还是异步消息”运维问“这个组件部署在哪台机器上”新人问“我从哪里开始看这张图”。你发现所有问题都指向同一个本质这张图只有元素没有逻辑。图表设计要解决的就是这个问题。它的核心不是“画”而是“设计”——设计读者从第一个视觉落点到最后一个信息节点的阅读路径。说得直接一点一张好图应该让读者在五秒内就能回答三个问题这里面有哪几类东西、它们之间什么关系、数据或流程从哪里开始到哪里结束。如果五秒钟答不上来图的设计就是失败的。我见过很多团队把架构图画得像一张地铁线路图密密麻麻的节点、花花绿绿的线条每个地方看起来都重要结果每个地方都没记住。这不是画工的问题是设计者没有做信息分级。真正有效的图表设计一定是先做减法再做布局先明确主链路再补充支撑细节先定语义再动手连线。1.2 图表设计的核心目标三个一眼做了这么多年图和评审图我总结出图表设计有三个最朴素的检验标准可以叫三个“一眼”。一眼看懂层级整张图的阅读顺序是清晰的最重要的模块处于视觉中心或起始位置次要内容退居边缘。这个靠布局和尺寸实现不是靠加粗和标红。一眼看懂链路数据流、调用流、状态流转这些核心路径线条走向必须连续、少有交叉而且方向明确。读图的人顺着线就能把整段流程走完不需要反复回头确认起点在哪。一眼看懂归属哪些服务归属于同一个业务域哪些节点是基础设施哪些是外部依赖通过分组背景框、颜色区间或者区域划分读者第一时间就能建立分类认知。这三个“一眼”听起来不复杂但真正做到位需要一套方法论支撑。下面这篇就把我从工具选型到最终落地的完整流程拆开讲。2. 动手之前先把工具和格式想清楚2.1 工具选型画布、代码、还是自动生成图表设计的工具选择是个老生常谈但又绕不开的话题。我的观点很明确没有最好的工具只有最匹配你团队协作习惯的工具。我在不同阶段用过四类工具各自优缺点都很明显。桌面画布类以 draw.io现在叫 diagrams.net为代表免费、本地文件、支持 Git 文本比对适合大多数技术团队。它保存为 .xml 格式配合 Git 可以做版本管理代码评审的时候 diff 虽然不够直观但至少能知道谁改了什么。代码绘图类有 PlantUML、Mermaid、Graphviz、D2 这几大派系。PlantUML 在 UML 图领域最成熟时序图和用例图的语法很顺手Mermaid 胜在轻量GitHub 原生支持渲染写 README 时嵌个 mermaid 就能直接显示Graphviz 的 dot 语言擅长自动布局适合节点非常多、手动排布不现实的关系图。这类工具最大的优点是“图随代码走”修改维护成本远低于拖拽式工具。在线协作类以 Excalidraw 和 Figma 为代表。Excalidraw 的好处是手绘风格能降低读者对图的“正式感预期”适合头脑风暴和早期方案讨论而且实时协作很流畅。Figma 更强大适合需要精致视觉输出的场景但学习和维护成本也高。自动生成类比如 AWS 架构图工具、K8s 可视化插件它们能从真实环境自动拉取资源并生成拓扑。这类工具生成的图作为巡检和盘点用很好但作为设计文档会非常混乱因为真实环境里的连线数量远超人类理解极限必须再经过手工整理才有可读性。我个人的实践建议是团队内部的技术方案文档与架构评审图优先选 draw.io 或 PlantUML对外交付或跨部门讲解可以用 Excalidraw 降低理解门槛节点超过三十个的复杂依赖关系图直接用 Graphviz/D2 自动布局再手工微调。2.2 源文件格式可维护性才是真正的门槛选工具时大家都关注画得爽不爽但真正决定图表设计长线价值的是源文件格式的可维护性。我见过太多团队用在线工具画完架构图导出一张 PNG 往文档里一贴就完事了。三个月后系统加了两个中间件想更新图发现原文件不知道存在谁的账号里就算找回来了也弄不清当时哪些线代表什么含义于是干脆重画一张。这类“一次性图”对团队是净负担。所以我现在对图表设计有一条硬规矩凡是会进入长期文档的图必须有文本形式的源文件并且跟随代码库一起管理。draw.io 的 .xml、PlantUML 的 .puml、Mermaid 的 .mmd 都属于这类。这样每一次改动都留下历史记录任何人都能在原图上做增量修改而不是推翻重来。这里补一句经验之谈如果你用 draw.io建议在文件属性里开启“压缩文件”的相反选项也就是保存为不压缩 XML这样 Git diff 还能勉强看出改动点。如果团队主要在 GitHub 上协作Mermaid 会是最省心的选择因为 PR 页面直接渲染评审体验最好。3. 布局、视觉与图层让图纸自己会说话3.1 布局的基本法则自上而下由左到右图表设计的布局规则不需要创新遵循读者天然的阅读习惯就是最高效的。大部分文化背景的人读书都是从左上到右下所以你的图也应该符合这个流向入口或起点在左上终点在右下。问清楚流向之后信息层级才能落位。对于架构图我习惯按“接入层 - 应用层 - 服务层 - 数据层”自下而上排列数据流是垂直方向。读者一眼看到最上层是用户入口最下层是数据存储中间是业务逻辑结构天然清晰。对于业务流程图主线流程一定要比其他分支更突出。方法有三种把主流程画得离左侧起点更近、给主链路的线条加粗、或者把主流程节点放在画布中轴线上让分支向两侧发展。对于时序图生命线的排列顺序就是参与者的调用顺序。PlantUML 的自动布局在这里表现很好因为它严格按消息顺序纵向展开不容易乱。还有一个小技巧当一张图里同时存在“部署关系”和“调用关系”时不要让这两类线条混在同一个方向。部署关系适合用包含结构表达比如设备机框里放服务节点调用关系用箭头线表达沿横向或纵向主轴线分布。混在一起画图就会变成盘丝洞。3.2 节点的呼吸感与分组策略很多图看起来“闷”核心问题就是节点之间太挤没有任何留白。节点和节点之间至少要保持一个节点宽度左右的间距这个空间是读者视觉识别边界的必要条件。没有呼吸感的图信息密度再高阅读体验也是负分。分组策略上一定要规划好“组大小”的粒度。节点数量在五个以下时可以用虚线圈或背景浅色块来划组坐标布局也可以。超过六个节点的大分组背景色区域会占据画布很大的空间内部如果没有再细分就会显得空旷。所以我一般建议每个分组框内放 3-6 个节点最合适超过六个就再拆子域。命名也是设计的一部分。分组的名字要回答“这一组是什么”而不是“这一组有哪些东西”。比如“订单中心”比“订单服务库存服务支付服务”更像一个分组名。节点自身的命名也有讲究在架构图里节点名用“服务名”而不是“服务器 IP”在部署图里节点名用“IP/主机名承载服务”让信息点一次到位。3.3 颜色语义与字体规范颜色在图表设计里是一把双刃剑。用好了读者秒懂分组类型用滥了整张图像霓虹灯招牌。我给自己定了一套配色规范执行了三年效果很稳定。我用不同色相区分类型而不是用同一种色相的不同深浅。比如核心业务服务统一用蓝色系基础设施用灰色系外部依赖用橙色系数据存储用绿色系。这样设计的逻辑是读者不需要读文字光看颜色就知道这个节点属于哪一类这是比图例更高阶的视觉引导。不要用红色表示“正常节点”。红色在所有文化语境里都自带警示含义如果你图中出现红色节点读者会下意识觉得它异常或者代表风险。除非这个节点真的是故障点否则不要用红色。同理绿色也不适合做核心业务色它让人联想到成功和通过适合表示健康检查、正常状态这类语义。字体规范容易被忽略但实际上对图的专业性影响很大。中文字体我统一用“思源黑体”或者系统默认无衬线体英文字体用主流无衬线体字号分三档图表标题 20-24px节点名称 14-16px注释和端口信息 10-12px。不要在一张图里出现三种以上字体也不要用艺术字体技术图的唯一目的是清晰不是美观花哨。4. 实操以一套分布式系统架构图为例4.1 从需求到草稿先画框图再画细节前面讲了不少设计原则这里我拿一个真实的例子把完整流程走一遍。假设我们现在要为“订单系统”画一张架构图读者是刚入职的新人工程师目标是让他看懂整个系统的核心链路和基础设施依赖。第一步我什么都不画先在纸上列清单核心服务有 Nginx 网关、用户服务、订单服务、支付回调服务、库存扣减服务数据层有 MySQL 主库、Redis 缓存、MQ 消息队列外部依赖有第三方支付渠道基础设施还有 Elasticsearch 日志集群。列完之后标出核心主链路用户请求 - 网关 - 订单服务 - 库存服务 - 支付渠道以及支付回调 - 订单状态更新 - MQ 通知下游。这个清单阶段就完成了信息分级核心链路上的节点用实线加粗画支撑性质的依赖用细线画基础设施用独立颜色区分。设计阶段不需要打开画图工具草稿越随意越好关键是先把结构和关系理清。第二步是确定布局方向。这张图我选择从上到下最上方是客户端和网关中间是核心微服务再往下是 MySQL、Redis、MQ最下面放日志集群和监控。外部支付渠道放在右侧偏下的位置用橙色框标识因为它虽然重要但不属于系统内部的纵向主链路。4.2 连接线和数据流的画法图表设计里线条信息的传达密度仅次于节点。很多图画得乱根源都是把不同类型的连接用了同一种样式。我的习惯是建立一套线型的语义约定并且在图例里写清楚。同步调用用实线箭头异步消息用虚线箭头数据读写用细实线不带箭头或者加粗双向箭头。返回结果不单独画线或者用和调用一致颜色但更细的线。这样做的好处是一眼看过去图的骨架信息是准确的哪条链路是请求/响应模式哪条是事件驱动模式。连线还有一个非常关键的约束减少交叉。如果两条线必然交叉我通常采用“跨线跳转”也就是一条线在另一条线上方拱起类似电路图的做法。这个在 draw.io 里可以设置线条样式为“实体”或“跳线”PlantUML 里用skinparam linetype ortho配合也能实现。还有一条经验如果交叉点超过画面总线条数的 10%说明布局选错了方向重新调整节点位置比逐个处理交叉更高效。数据流的信息标注也值得留意。很多新人画线只画方向不标协议和内容后来看的人根本不知道这条线上跑的是什么。我在线上会加简短注释比如“HTTP/JSON 下单请求”“MQ Topic: order_done”。注释放在线的中段偏起点位置不会和节点边框重叠。4.3 导出与交付一张图插进文档的完整流程画完图只完成了一半工作导出和交付的细节同样影响最终效果。这一步我踩过的坑比画图阶段还多。首先是导出格式。如果图要放进 Word 或 PDF导出 PNG 时分辨率一定要选“200 DPI”以上否则放大后全是锯齿。draw.io 的导出对话框里可以直接设置缩放比例我一般设置 200% 再导出这样在文档里做局部放大也不会糊。如果图要放进网页或者 Markdown导出 SVG 格式是更好的选择体积小、无限清晰、还能被搜索引擎索引文字内容。然后是放置位置。前后文要对应不能把图孤零零放在文档最后。我更倾向于把架构图放在文档第一章的“整体设计”小节流程图放在对应业务场景的章节里。并且图下方要配一段 3-5 行的说明文字概括图的核心结论而不是把图当摆设。这条规则保证读者不点开大图也能理解图的中心思想。最后是维护。图放进文档后必须在文档里标注源文件的位置或者维护方式。比如图注写成“架构图源文件见 /docs/diagrams/order-system.drawio”。这样半年后有人要改图他知道去哪里找文件而不是对着 PNG 干瞪眼。5. 常见问题与排查技巧实录5.1 线条交叉无法避免时的处理办法即使布局规划得再周全大型图表设计里也很难做到零交叉。我在一张超过四十个节点的依赖关系图里遇到过二十多处交叉根本不可能靠手工一个个调整。这时候我的处理顺序是先分层次处理。把图分成若干子图让子图之间通过总线式连接而不是两两直接连线。比如六个服务都要访问 MySQL不要画六条线指向数据库图标而是画一条总线标注“JDBC 连接池”六个服务就近挂在总线上。这个技巧可以把交叉点直接消灭一半。如果交叉仍然存在就利用画布的绕行空间。draw.io 里可以设置线条为“特定路径”而不是“最短直线”手动控制线条从空白区域绕行。尽量让交叉发生在空白区域而不是节点上方这样即使避免不了交叉读者的视线也不容易被切断。还有一个反直觉的技巧在密集的网状结构中与其消除所有交叉不如故意把一部分信息省略。因为读者真正需要追踪的路径往往只有两三条把次要关系折叠进节点内部的“详情见文档 X”可以让主要链路保持绝对清晰。我经常在一张主图之外配两张子图分别表达不同维度的关系效果优于硬生生把所有内容塞进一张图。5.2 图一放大全糊了问题出在哪这个问题我收到过不少同事的吐槽明明在画布里看着挺清晰导出图片放进文档一放大就全是马赛克。原因基本都是导出设置不对。draw.io 默认导出 PNG 的缩放是 100%这个分辨率在普通屏幕上问题不大但放到高 DPI 屏上或者文档打印时就撑不住了。解决办法是导出时把缩放拉到 200% 或者更高。PlantUML 导出 PNG 也类似可以通过skinparam dpi 200来避免糊图。另外还有一个非常容易被忽视的问题字体嵌入。如果电脑上装了某个字体导出 PNG 时正常显示但把源文件发给同事对方打开时字体缺失图里的中文变成豆腐块或者被替换成奇怪字体。解决办法是尽量使用通用字体或者在交付时同时附上导出好的 SVG/PNG避免让人家临时打开源文件渲染。如果你用 Mermaid 并且图片是从 GitHub 或在线渲染器生成的要注意渲染器的字体服务可能不支持中文结果文字变成乱码。这个问题的规避方案是中文字符标注尽量精简必要时用拼音或英文替代或者提前用支持中文的渲染服务。5.3 图表维护的真实痛点与对策图表设计最难的不是画第一版而是保证它不会在三个月后成为一张“历史文物”。我统计过自己团队的文档有大约三分之一的技术图在半年后就与实际系统不一致了。原因无非几种服务拆分、基础设施变更、依赖组件调整但没有人同步更新图。要让图表活下来我推荐几个经过验证的做法。把图放进 CI 检查的范围。PlantUML 或者 Mermaid 的源文件如果随代码库管理可以在 CI 流程里加一步编译渲染文件语法错误时直接让构建失败。这样至少保证图始终能被正常渲染不会因为语法失效而悄悄坏死。在代码评审模板中加入“是否影响了系统架构”的勾选项。改动了服务拓扑直接把架构图源文件一起改掉并且把修改后的 PNG/SVG 截图贴在 PR 描述里。规则很简单谁动了架构谁负责改图。定期做图文档的“体检”。我每个季度会抽查三到五张核心架构图和线上真实的部署状态做对照发现偏差就当场修正。这不用花很多时间但能防止错误信息长期滞留在文档中误导后来者。再分享一个小习惯我在关键图上会标注“最后更新日期”和“责任人”。这个信息看似简单但读者看到最近更新日期是一周前会更有信心看到是半年前就会主动核验。它可以倒逼图的维护成为常规动作而不是查资料时的顺带行为。我个人这两年最大的一点体会是图表设计的能力不是一个画图软件的操作能力而是一个人对信息做分层、取舍、排序和视觉转译的综合能力。工具永远只是为了承载设计意图。真正决定一张图是让读者秒懂还是让人眩晕的是你在打开画布之前有没有先想清楚——这张图的核心读者是谁、核心链路是哪条、哪些信息可以舍弃。每次动手前多花五分钟想清楚这三个问题画出来的图和以前会完全是两个水准。