架构图设计这件事,我过去三年里画了不下两百张。从最开始拿Visio拖框拖到怀疑人生,到后来慢慢摸清楚分层逻辑和配色套路,再到现在基本能做到一张系统架构图半小时出稿、改稿不超过三轮。这个过程中踩过的坑、攒下来的经验,我觉得比很多教程里讲的那些花哨技巧都值钱。这篇文章我就以“diagram-design”为切口,把架构图设计从“想清楚画什么”到“怎么画得专业”再到“后续怎么维护”这一整套流程揉碎了讲清楚。
先说个基本判断:架构图的难点从来不在工具,而在“画之前怎么想”。很多人一上来就打开画板开始拖拽节点,画到一半发现层次乱了、线交叉了、文字放不下了,然后陷入无休止的调整。这是最典型的错误姿势。正确的做法应该是先做信息架构,再做视觉表达。文字表达和图示表达遵循的完全不是一套逻辑。文字擅长线性叙事,一句接一句讲清楚因果;图示擅长展现空间关系和群体结构。你把一段文字翻译成图,如果仅仅是做“关键词提取+框线连接”,那出来的图一定是生硬且难懂的。
我自己在动手画图之前,会强制自己先回答三个问题:这张图要给谁看?他想从中获取什么决策信息?他看到这张图之后的下一步动作是什么?这三个问题的答案直接决定了图的设计方向。给技术评审看的时序图,必须精确到方法级和消息顺序;给业务方看的系统链路图,则需要弱化内部细节、突出核心流程和数据流转。给新人培训用的架构图,要把依赖关系和启动顺序讲清楚;给运维同学用的部署图,端口、IP、容器分布优先级最高。目标不同,图的形态和抽象程度完全不一样。很多人画的图“看着挺全但没法用”,根源就在于没在动笔之前把这个问题想清楚。
1. 先理信息架构,再谈视觉表达
1.1 画图前的信息梳理清单
我在动笔前习惯先用一个非常笨的办法:在纸上或者在空白编辑器里,把这张图需要出现的所有“名词”列出来。比如画一个微服务架构图,我会先把所有服务名、中间件、外部依赖写下来;画一个数据流图,我会把数据源、处理节点、存储落地、消费方全部列全。这一步看起来质朴,但能筛掉后期至少一半的返工。
列完之后做两件事:分组和定层级。分组就是把名词按业务域、按技术层、按部署环境等维度归到几个桶里。定层级则是区分出“核心主干”和“辅助细节”。打个比方,画一个外卖下单系统的架构图,用户App、商家端、配送端是核心主干,必须放大并放在视觉中心;而日志采集、监控告警、灰度发布这些属于辅助系统,就往下放、往小了画。层级剥离清楚之后,你才知道眼睛重点该落在哪里。
这个阶段输出的应该是一份纯文字的结构清单,不是图。一定要注意,先列清单(文字)再画图,而不是反过来。文字是比图示更精确的信息组织方式,先用文字把逻辑边界和从属关系钉死,后续画图就是“翻译”而不是“创作”。
1.2 分层定架构,位置即权重
架构图设计的第一个核心概念是“层”。我在实际操作中会把一张图拆成4到6个层次,从上到下依次是接入层、应用层、服务层、数据层(外加旁路的支撑层和运维层)。不同行业的图会有不同变种,但分层思路是共通的。
分层的核心意义在于:人眼对纵向位置的敏感度极高,从上往下扫描是本能。你刻意把“用户侧”放在顶部,把“基础设施”沉到底部,读者不需要看文字就能感受到这张图的叙事方向。这种“位置即含义”的设计原则,比任何花哨的视觉技巧都重要。
具体到实践中,我会遵循几个分层的硬性要求。第一,同一层内的元素要水平对齐,绝对不能忽上忽下。如果某层只有一个节点,也要把它放在该层次区域的中心轴线上。第二,层与层之间的间隔尽量统一。我常用的间距标准是层间距约为节点高度的1.5倍左右。太密显得拥挤,太疏显得散架。第三,层与层之间如果存在跨层关联(比如应用层直接读写数据层),连线可以跨层画,但这种边一定是你这张图里最需要强调的“例外路径”,数量控制在个位数以内。
表达三要素“节点、连线、容器”本身就是构图的全部元素。节点代表实体,连线代表关系,容器代表边界。画得好的架构图一定是对这三者做了严格的主次管理。同一个层级的节点保持同等大小;非核心细节节点用淡色调;连线用实线默认、虚线辅助、粗线强调主干流量;容器用来表达网络区域或部署边界。
2. 核心表达逻辑与排版原则
2.1 布局策略的选择与适用
节点的布局方式直接决定了图的命运。我见过太多画得工整但完全看不懂的图,原因就在于布局没有遵循人的阅读习惯。人眼的视觉动线是从左上到右下(Z型扫视)的,架构图最好是沿着这条动线来安排信息流。最理想的状态是:
左上角放入口/请求发起方,中间按处理链路展开,右下角放最终存储或输出端。读者第一次看这张图,视线自然地从左上扫到右下,基本就把整条链路看完了。
具体布局我常用三种策略。第一种,层级布局,适合技术架构图。从上到下分层,每层内部再从左到右平铺,线条尽量在一个方向上延伸。第二种,中心辐射布局,适合数据流图或核心服务依赖图。核心节点放在画布中心,围绕它一圈排开附属节点。第三种,分簇布局,适合微服务治理图、多项目大盘图。把强内聚的一组节点先聚成一个小集群,再把小集群视为一个整体进行排列。
选择布局时有一个基本判断标准:这张图的阅读顺序是线性还是非线性的。如果是线性链路(比如用户请求打进来经过网关再到服务再到数据库),层级布局或自上而下的流式布局几乎是最优解。如果是网状依赖(比如一组微服务之间的调用关系),那分簇加中心辐射的混合模式更合适,中心辐射布局能让核心依赖一目了然,但要注意辐射线数量多了之后必然交叉,交叉的连线是架构图的大敌。
连线交叉的问题在设计阶段就要预防。我的做法是:先把所有需要连线的关系在清单里编号,然后检查是否有A-B和C-D两组边相互交叉的情况。如果有,优先调整节点的排列顺序来避免;如果调整不了,就考虑增加一个“中间跳转节点”,把一条长交叉线拆成两段没有交集的短线段。组内加一个“汇总网关/聚合层”也能在一定程度上减少连线数量。
2.2 处理长链路与嵌套结构
画业务链路或时序图的时候,经常会遇到一条链路上挤了太多节点的情形。十个以上的节点一条线拉过去,画出来就像一串冰糖葫芦,读起来很容易断气。我解决这类问题的办法就两个字:分组。
把链路中功能相近、归属同一系统或同一个团队的节点折叠成一个“分组节点”。比如“鉴权模块”内部可能包含登录校验、Token校验、权限验证三个子步骤,但在上层链路图中就折叠成“鉴权服务”一个节点,需要细看时再拆开拉一张独立的子图。这就是“分层抽象”的工程思想在画图上的体现,也是表达复杂系统时最有效的标准化手段。
嵌套结构也有类似讲究。微服务里嵌套Feign调用、K8s里嵌套Pod,这些从属关系不能靠拉线表示,应该用“容器套容器”的方式表达。外层画一个大的虚线框代表服务边界或集群,框内再放具体的子模块。但是嵌套层级不建议超过三层。超过三层读者会失去空间感,分不清到底谁属于谁。如果真需要表达四层以上的嵌套,拆分视图比重叠容器要清晰得多。
嵌套容器还有几个细节要注意:同名节点在不同容器中要加前缀区分,避免读者混淆。容器边框用虚线还是实线也有讲究,实线代表强边界比如进程级、物理机级,虚线代表弱边界比如命名空间级、逻辑分组级。这个约定必须全局一致,不能这个容器用虚线、那个容器用实线,否则读者会对边界强度产生误判。
2.3 配色设计的“少即是多”原则
配色是架构图设计里最容易被忽视又最影响观感的部分。我见过大量花里胡哨的架构图,恨不得每个节点一个颜色,最后画完整个界面像被打翻的调色盘,找不到重点。
我的配色方案有一套死规矩。整张图的颜色不超过四种:一种主色、一种辅助色、一种强调色、一种底色/中性色。主色承载所有同类元素的着色,辅助色用于区分不同类型的实体(比如外部系统用灰色、内部服务用蓝色),强调色只出现在这张图最想让人注意的那一两个元素上,底色与中性色用来衬托文字和边框。
好的架构图有一个评判标准:把图片缩到50%大小甚至变成马赛克,依然能从色块分布看出图的疏密和节奏。如果缩略图看起来就是一团均匀的色块,说明你的配色太平均了。应该在缩略图的尺度上,让视觉焦点(强调色占的区域)依然能被一眼识别。
我再提供一个我自己常用的色板参考(总配色数严格控制在6种以内):
| 用途 | 色值参考 | 使用场景 |
|---|---|---|
| 主色(内部核心服务) | #3B6EA5 深蓝系 | 业务模块、核心微服务 |
| 辅助色(数据存储) | #2D8F6F 墨绿系 | MySQL、Redis、数据仓库 |
| 外部依赖 | #74808A 灰蓝系 | 第三方API、外部系统 |
| 强调色 | #E05B4C 砖红系 | 链路中的重点环节/故障点 |
| 底色 | #F7F8FA 近白浅灰 | 画布背景 |
| 警戒色 | #D9A441 琥珀色 | 警告类标记、灰度区域 |
这套色板是我在实际岗位上总结的“安全牌”,怎么组合都不会显得廉价。真正的原则是低饱和、低对比、大块面。设计稿里黑白打印或者色盲模拟过一遍依然能靠灰度区分,这就算过关了。
说到颜色,可以延伸讲一下色弱的可用性:大约8%的男性和0.5%的女性存在某种形式的色觉缺陷,红绿搭配的“红绿色盲陷阱”在团队里一定会遇到。方案是用“亮度+形状”而非单纯靠色相来区分信息。也就是说,不同类型的节点不仅颜色不同,最好连形状也不同(圆角矩形表示服务、直角矩形表示外部系统、胶囊形表示消息队列)。颜色只是辅助,形状才是主区分。
3. 实操过程与工具链方案
3.1 工具选型怎么定
画架构图的工具五花八门,我个人的经验是,工具不在多,在于匹配场景。Visio适合企业标准文档交付,但日常迭代改稿卡顿、导出协作麻烦;ProcessOn轻量协同可以,但复杂图一多,免费版和图例限制就很让人头痛。真正的“日常主力”我推荐以下三款:
| 工具 | 适合场景 | 核心优势 | 注意点 |
|---|---|---|---|
| draw.io(现名diagrams.net) | 本地/私有化部署、复杂架构图 | 免费、文件存本地、支持命令行导出 | 界面朴素但功能强大 |
| Excalidraw | 快速白板草图、方案讨论 | 手绘风格降低心理预期、实时协作 | 不适合精确复杂的大型图 |
| PlantUML | 代码生成图、持续集成场景 | 文本定义图、版本可控 | 学习语法有成本 |
如果是要放进Git仓库里做版本管理、跟着代码一起走,PlantUML是首选;如果要求快速协作、标注讨论,Excalidraw体验极其顺畅;如果是严肃的技术方案文档、上线评审材料,draw.io的标准化程度和专业感最可靠。实际上我见过很多团队用PlantUML写系统文档,效果非常好,尤其是配合CI/CD自动生成架构图,能保证文档跟上代码演进。架构图是“活的文档”这一点在后面的维护章节我会展开讲。
3.2 一整套实操流程:以“某跨平台票务系统的部署架构图”为例
我不讲空洞理论,拿一张实际的部署架构图来拆解整个实操流程。场景假设是这样的:某跨平台票务系统要上线,涉及容器化部署、若干微服务、消息队列和数据库,需要画一张交付级的部署架构图。
第一步,梳理信息与分组。先列名词:用户端App、Web管理后台、网关、用户服务、订单服务、支付服务、票务库存服务、消息队列、用户库、订单库、缓存、日志服务、监控服务、配置中心。分组之后结果是:终端接入层(App、后台)、接入层(网关)、应用服务层(用户/订单/支付/库存)、中间件层(MQ、缓存、配置中心)、数据层(用户库、订单库)、支撑层(日志、监控)。
第二步,确定布局。我选择标准层级布局,垂直六层,极少数跨层连线(网关直接操作日志除外,这一个跨层边用粗虚线表示并在图例说明)。用户入口放在左上,日志监控作为支撑层斜向放在右侧,整个图的视觉动线是流畅的左上到右下。
第三步,elaborate容器与节点的表达。边界的分组:外层画一个大虚线框“K8s集群”,内部再画“服务网格”和“数据面”子框;数据库单独放一个独立区域。将中间件层画成胶囊形节点,强调其“管道/缓冲”的语义。
第四步,规则化连线。核心请求链路用深色粗实线,异步消息用浅色虚线(并标注MQ的topic名),配置与治理类调用用更浅的细线。线始终走通道、绕开节点,绝不穿过实体区块。
第五步,配置颜色与图例。按照上文的色板,内部微服务统一主深蓝,数据存储用墨绿辅助色,中间件用灰蓝,强调色砖红只给了“订单服务+订单库”这条链路节点,寓意核心业务链路。图右下角补一张图例,说明线型、框型的含义——这是交付级图与草稿级图的关键区别,没有图例的图都是不合格交付。
这套流程走下来,基本上动手画的时间只占四分之一,大部分时间都花在分析和布局规划。真正操作draw.io的时候,拖拽节点就是个“翻译”动作,从容不迫地一个个摆上去就好,全程不需要犹豫该画在哪。因为你已经写清楚了该有什么、放哪里。
第四步里还有一个细节:节点的命名规范。中文场景里我建议用“服务名-功能描述”的格式,比如“用户服务-注册登录”,而不是光秃秃的一个“用户服务”。但同一个图内不能出现两个同名的节点。如果两个环境都叫“交易服务”,那就要标注清楚是“交易服务-线上”和“交易服务-预发”。节点之间用短横线连接,而不用长横线和空格,避免出现不明所以的断连。
3.3 文本标注与附加信息
好的架构图不仅有节点和连线,还要有精准的文本标注。文本是图的“注释系统”,用来解释那些图形本身无法传达的信息。比如“这一条链路走的是长连接通道”“这个服务目前只在灰度环境中启用”。这些信息如果只靠图形表达,要增加很多视觉元素的复杂度,反而把图搞脏。
我对文本标注有三条规范:第一,节点标题不超过12个字,超了就拆主标题加副标题;第二,连线上如果要标注(比如协议名、端口号、频次),优先标在线的中段,别标在线的两端,否则容易被节点遮挡;第三,关键信息尽量放在图例或底部备注里,不要散落在画布上。散落的注释多了,视觉噪音就上来了。
图例是一个很容易被忽略但极其重要的环节。只要图里出现任何一种你不知道它确切含义的视觉元素——不管是一个特殊颜色、一种虚线样式还是一个带箭头的奇怪标记——就必须在右下角或者不碍事的位置补充图例说明这部分含义。图例是架构图的“共享词汇表”,是为了防止读者自己的脑补方向与设计者意图不一致而发生误解。
4. 常见问题与排查技巧实录
4.1 线条交叉与乱线的治理方案
交叉线是架构图最刺眼的“脏点”。我的排查方法是:画完第一版之后,把图导出成PNG,在图片上用肉眼扫视所有连线,做一个“交叉测试”。凡是出现三条以上连线相交的区块,就是需要优先治理的重灾区。
治理方案有三个层级,从轻到重依次是:
调整同一层内节点的排序。比如把“订单服务”和“支付服务”这两个互动频繁的节点靠近排列,自然缩短连线,减少跨越其他节点的可能。这个办法最轻量,也最常用。
增删“中转节点”。如果排列顺序怎么调整都有交叉,说明这一层应该有一个聚合入口。比如在多个服务与监控系统之间加一个“日志采集器”节点,把散落的监控连线先收敛到采集器,再由采集器统一拉一条线到监控系统。连线数量从N条降到1条,交叉自然消失。
拆分视图。如果治理无效,说明这个图的信息已经超出了单图承载的合理上限,拆成“主链路图”和“辅助支撑图”两张图更清晰。不要硬塞。
4.2 信息过载:页面放不下怎么办
信息过载跟前者不一样,交叉只是拓扑问题,过载是语义问题。如果你的图看起来“密密麻麻全是东西”,大概率是你把两层抽象放到了同一张图里。
拿前面的票务系统举例:如果读者关心的是订单从创建到支付到库存扣减的核心链路,那运维侧的日志采集与链路追踪细节就不该出现在主图上。凡是跟主视角无关的节点,要么删掉,要么折叠成一个“支撑系统”的聚合节点。一张图只服务一个核心视角,其他的视角让位给其他图。
4.3 更新困难:架构图老化,是谁的问题
我见过太多公司架构图仓库里的图,最新更新日期还停留在两年前。图一旦不更新,价值就急剧衰退,甚至还会误导新人。这个问题听起来是维护制度的问题,但根子出在“图的可维护性”上。
架构图必须跟上系统的演进速度,如果每次改动都牵动十来个节点的坐标调整,自然没人乐意维护。这就要回到前面强调的设计原则:位置即含义、容器表达层级、图例统一规范。如果图的结构本身是稳定的,“新增一个服务”只需要在对应层级的节点堆里加一个小方块、补两条线,再调一下布局位置就行。结构稳定、含义清晰、操作成本低,大家才更愿意高频更新,图和代码才能保持同步。
一些团队把治理能力下沉到代码里:用代码生成图。定期扫描服务注册中心里的实例与依赖,自动画依赖图;对不合理的依赖关系执行告警。这个思路值得投入,因为人工画的图永远有滞后风险。
4.4 可读性的自检清单
我每次画完图,不管多急,出品前都要过一遍固定自检。这个清单是拿无数张返工图换来的,分享出来大家可以抄作业:
- [ ] 缩略图模式下,还能不能一眼看到核心链路?
- [ ] 有没有超过6种以上的颜色在同时使用?如果有,强制削减。
- [ ] 每个节点标题是否都在12个字以内?
- [ ] 是否存在无标注的连线?每条线是否都能说清它代表什么?
- [ ] 是否提供图例?图例是否覆盖了所有非默认视觉元素?
- [ ] 读图顺序是否顺畅(从左到右/从上到下)?有没有视线被迫跳跃往返的情况?
- [ ] 图右下角有没有留下修改日期与维护人信息?
- [ ] 一张图是否只包含一个核心主题?
- [ ] 布局是否支持后续新增节点时不会推倒重排?
如果你的图能扛过上面这9条,基本就可以大胆发出去了。
再补一个细节:导出格式的选择。交付给人看的图,用PNG或SVG。PNG适合快速预览和聊天里转发,SVG适合嵌入网页或文档,可以无限缩放且体积小。如果是大家协同编辑,存一份源文件格式(比如draw.io的.xml或.excalidraw)到团队网盘或Git,跟代码放一起,这样后续任何人都能接着改。
4.5 一个真实项目的图演化过程
我印象很深的一个项目是给某内部管理系统画“服务依赖全景图”。第一版,我什么都不懂,把所有微服务拉出来平铺在画布上,然后用十分钟拖了上百条连线。画完之后整个图像一张蜘蛛网,谁看谁摇头。后来被逼着反思,把图删了重画。第二版我做了分簇与分层,核心服务放中间,支撑系统围绕外圈,依赖连线全部改成“从左到右的方向性描述”,图清晰了好多。再后来我学会了图例和颜色限制,整个图的信息传达效率有了质的飞跃。到最终版,这张图被做成了大屏图挂在我们组门口的电视上,每天滚动展示,成了全组的“系统地图”。
这个案例说明了什么?说明架构图的价值上限取决于设计者的系统抽象能力,而不取决于绘图工具。你的图丑,不是因为不会用软件,是因为没想清楚该表达什么。
最后分享一个我本人一直在用的习惯:画图前先做一次“口述测试”。闭上眼睛,尝试用三句话把这张图的逻辑说清楚。说不清楚的,就是没想明白;能说清楚的,直接动手画。这个习惯帮我省掉了大量无效的画图时间。一张好图,本质上就是一段优秀的“视觉化逻辑叙事”,你的逻辑有多清楚,图就有多好懂。
我真心建议每一个做技术、做产品、做方案的人都认真练一练架构图设计这件事。它不只是画图技能,更是一种结构化的思维方式。画多了之后你会发现,自己梳理问题、拆解系统的能力也在肉眼可见地提升。