从Visio到D2:声明式架构图工具实战指南
干这行十几年,我画架构图的工具换了一茬又一茬。早期跟着同事用Visio,后来换Mac之后试过OmniGraffle,再后来团队流行用PlantUML和Mermaid,但每次画复杂系统的架构图,总觉得差一口气。直到我在GitHub上刷到D2这个项目,看到2.5万+的star,那句“一种现代声明式图表脚本语言”的介绍,突然让我有一种“对,这就是我想要的”的直觉。
D2的核心思路其实简单到让人怀疑:你不用再手动拖拽方块和连线,而是像写配置一样把图的结构描述出来,它自动负责排版和渲染,最终输出SVG或PNG。乍一听好像和PlantUML差不多,但真正用下来会发现,它在布局、样式、可读性上的完成度,完全不是一个量级。这篇文章不吹不黑,就记录我从Visio迁移到D2的真实过程:语法怎么上手、架构图怎么落地、中途踩了哪些坑,以及哪些场景我劝你别跟着换。适合后端、前端、运维、架构同学,也适合所有要画系统图、部署图、流程图的人。
1. 先搞清楚D2到底是什么
1.1 一句话解释D2
D2是一个开源声明式图表脚本语言加渲染引擎。所谓“声明式”,意思是你要做的是描述“图里有哪些元素、它们之间什么关系”,剩下的位置计算、连接线路径、分层布局,都由D2自己搞定。举个例子,你想表达“用户请求到达服务器”,在Visio里要先拖一个用户的图形,再拖一个服务器的图形,然后手动画一条带箭头的线,还得调整箭头角度让它不穿字。在D2里,一行代码就够了:user -> server。
这也是我一开始被吸引的最大原因。架构图本质上表达的就是两件事:系统里有哪些组件,组件之间如何通信。Visio把90%的操作精力花在了“怎么画得好看”上,而D2把“怎么表达清楚”还给了你。它不阻止你做样式定制,但默认状态下出图质量就足够高,不需要你花大力气去对齐、调色、摆放。
1.2 和Visio、PlantUML、Graphviz比一圈
先说Visio。它代表了经典的手工绘图思路:自由度高,想怎么拖就怎么拖,但自由过头就是维护成本灾难。一张图拖三小时,箭头还是歪的;多人同时改一份Visio文件,版本一多基本等于失控。我还在上一个项目见过同事打开一个上千个shape的Visio文件,电脑风扇直接起飞,随便拖动一个元素,整张图重新排布,然后当场卡死。这种体验过的人应该都知道有多痛。
PlantUML和Mermaid解决了“文本画图”的问题,但也各有短板。PlantUML语法有点反人类,排列经常需要反复调整;Mermaid在流程图上很强,真到了复杂分层架构、跨多个系统边界连接的时候,表达力明显不足。Graphviz能画非常大的图,但dot语法那套东西,愿意认真学的人真不多。D2站在中间:语法贴近直觉、布局自动、输出好看,尤其适合软件架构图、云架构图、网络拓扑图。
| 工具 | 工作方式 | 上手难度 | 布局控制 | 版本控制 | 默认出图颜值 |
|---|---|---|---|---|---|
| Visio | 鼠标拖拽 | 低 | 自由但费时 | 差 | 看个人水平 |
| PlantUML | 文本脚本 | 中 | 一般 | 好 | 一般 |
| Mermaid | 文本脚本 | 低 | 一般 | 好 | 中上 |
| Graphviz | 文本脚本 | 高 | 强 | 好 | 一般 |
| D2 | 文本脚本 | 低 | 较强 | 好 | 高 |
所以我的结论很明确:D2不是要全方位取代Visio,而是在“需要持续维护、多人协作、自动生成、版本管理”的架构图场景里,它比Visio可靠太多。Visio依然适合那些一次性的、需要精细排版的图形工作,但如果是跟着代码走的技术图,D2是更合理的选择。
2. 我为什么下决心把Visio换掉
2.1 架构图终于可以进Git了
以前团队用Visio维护架构图,最大的痛点是:图躺在个人电脑里,换一个人接手就不知道最新版在哪。后来大家又迁到共享盘,结果目录里全是“架构图_v2_final_终版_真的不改了.vsdx”这种鬼名字。用上D2以后,架构图就是一个纯文本文件,跟在代码后面一起提交到Git仓库,每次变更都能清清楚楚看到diff。评审代码的时候顺手把架构图也review掉,流程自然得不得了。
这对很多团队来说是观念层面的变化。架构图不再是一个交付物,而是代码库的一部分,和README、接口文档一样持续演进。D2文件是文本,意味着你可以用常规的代码规范去约束它:缩进、注释、命名、结构。你甚至可以给它写单元测试——至少可以检查关键节点是否还存在、关键链路是否被改丢。
2.2 改图成本从“小时”变成“秒”
在Visio里改一次架构图,我心里的预期是至少留出半小时:拉线、对齐、调色、更新文字、处理交叉线,运气不好还要重画。用D2之后,改一个依赖关系就是一行文本的事。比如把订单服务直连MySQL改成走消息队列,只需要把 order_svc -> mysql 改成 order_svc -> mq,布局引擎自动重排,五秒钟后SVG已经重新生成好。
这个变化在技术方案评审时尤其明显。以前开会时大家对着旧图争论,谁提出改方案,谁先回去改图,下一轮评审才能看到新版本。现在我们可以当场改D2文件,投影仪上实时重新渲染,新方案立刻可视化。相当于把架构图从“事后文档”变成了“讨论工具”,这个体验一旦用过就回不去了。
2.3 和自动化、文档系统天然契合
D2命令行工具设计得很适合嵌入流水线。你可以在CI/CD里加一个步骤:每次代码提交后自动渲染架构图,然后把SVG发布到文档站或者作为构建产物归档。文档系统如果用MkDocs、Docusaurus这类工具,直接引用生成的SVG文件,文档自动跟着代码更新。这一点对基础架构团队和平台工程团队尤其值得尝试。
还有一个容易被忽略的点:D2生成的SVG是结构化文本,后续可以做程序化处理。比如批量替换主题色、给不同环境的图打上环境标签、把多个子图拼成总览大图,这些在Visio里几乎不可能实现。D2把架构图变成了“可编程的资产”,你可以用任何你熟悉的技术栈去操作它。
3. D2语法核心:半小时上手
3.1 安装D2
D2安装没什么门槛。macOS用户最简单,直接一条命令就搞定。Windows用户可以用包管理器,也可以去GitHub Releases页面下载对应平台的压缩包,解压后把可执行文件加进PATH。Linux发行版也有对应的仓库方式。装完在终端敲一下 d2 --version,能输出版本号就说明环境正常。
这个工具体积不大,运行时依赖也少,渲染引擎都打包在二进制里,不需要额外装Java运行时或者Node环境。这一点比PlantUML需要Java、Mermaid在浏览器里渲染要省心得多,尤其是在CI容器里使用的时候。
3.2 第一个文件
新建一个 hello.d2,内容只写一行:
然后执行:
同目录下就会生成 hello.svg。用浏览器打开,你会看到一条从 user 指向 server 的箭头。这个例子有点傻,但它说明了一件很重要的事:D2把“连接”这个最核心的图元素抽象成了 ->,整个语法体系就是围绕节点和连接展开的,没有太多弯弯绕绕。
通常你会想给节点显示中文名,在节点名后面加冒号和展示文字即可:
冒号前面的 user 是节点ID,用于引用;冒号后面的“用户”是实际显示在图形上的文字;连接箭头后面的 HTTPS 是连线的标签。这套规则非常容易记住。
3.3 容器、方向、样式
实际架构图很少是扁平的,一定会有分组。D2用花括号表示容器,相当于Visio里的“框选分组”或者“泳道”:
容器可以嵌套容器,节点可以放在任意层级,连接时用点号引用容器内的节点,比如:
这个表达能力非常契合软件架构图。你想表达“用户到API网关”“API网关到核心服务”“核心服务读数据库”,直接写链路就行,不需要手动画框框把服务圈起来。
控制整张图的排列方向也很简单,文件顶部加一行:
默认可能是从上往下,改成 right 后整张图从左往右展开。对于微服务调用链这种有明确流向的图,横向排布通常比纵向更清晰。
样式方面,D2提供了类似CSS的属性写法,比如给节点加颜色:
也可以通过渲染参数切换主题,甚至有一个手绘风格参数,出来的图跟白板上画的一样,在方案宣讲时反而更容易让观众放松下来。我的经验是,不同项目用不同主题,架构图挂在Wiki上,一眼就能认出来是哪套系统。
3.4 实时预览和导出
日常调图的推荐工作流是开一个监听模式。D2提供了watch参数,启动后会监听 .d2 文件的变化,每次保存自动重新渲染。我习惯左边开编辑器,右边开浏览器,改完代码立刻切过去刷新,体验和写前端热更新差不多。
导出格式默认是SVG,也支持PNG、PDF等。需要高清位图时用类似命令:
这样生成的PNG是2倍分辨率,直接放PPT里放大也不会糊。核心原则是:能导SVG就优先SVG,矢量格式在网页和文档里表现力最好,位图只是为了兼容某些旧文档格式。
4. 实战:用D2画一张可落地的微服务架构图
4.1 先画容器分层,再画连接线
很多初学D2的人容易犯一个错:把所有节点堆在根上,结果自动布局一塌糊涂。正确做法是先想清楚分层和分组。我这里用一个电商平台的微服务架构图来演示,目标表达四层:用户端、接入层、应用服务、基础设施。每一层用一个容器表示,层与层之间用连接线表达调用关系。
这种分层结构天然适合D2的容器语法。画的时候先搭骨架,不要一上来就写样式。骨架对了,图的信息就对了大半;样式只是锦上添花。
4.2 完整的D2代码
下面是一个可以直接运行的示例:
执行 d2 shop.d2 后,你会得到一张结构清晰的微服务架构图。核心关注点全都在:请求从哪里进来、网关怎么分发、服务怎么依赖基础设施。
4.3 视觉优化与重点突出
画完之后一般还有一步:让重点更突出。默认样式中所有节点颜色一样,阅读时找不到视觉重心。我的做法是把核心链路节点加上和普通节点不同的填充色:
这样网关、负载均衡、数据库这些关键角色一眼就能看到,整体层次感立刻提升。D2的颜色属性支持得很细,边框、填充、字体颜色都能改,但我不建议过度设计。架构图是给人看逻辑的,不是比谁颜色多。
4.4 顺带解决“泳道”问题
很多人搜“visio如何删除多余的泳道”,说明在Visio里调整泳道边界的体验实在糟糕。D2虽然没有“泳道”这个原生概念,但容器完全可以实现同类效果。你可以把每个部门或系统边界画成一个大容器,内部放节点,跨容器的线会自动绕开容器边界。想删除一个泳道?把对应的花括号块删掉,整张图自动重排,不需要手动拉边框、挪泳道条、重新对齐连线,体验完全是两个时代。
5. 常见问题与避坑实录
5.1 中文乱码或显示成方块
这是刚上手D2时最容易碰到的问题。D2默认字体对中文字形支持不好,如果你用中文标签,渲染出来很可能是方块或者直接消失。解决办法是显式指定一个中文字体文件。macOS下可以指定系统自带的苹方字体:
Windows下可以用微软雅黑对应的字体文件路径。在团队项目里,通常会把字体文件放在仓库的fonts目录下,统一用脚本传入,这样同事拉下来就能渲染出正确效果,不会因为各人系统字体不同导致图长得不一样。
5.2 布局不是我想象的那样
声明式画图面临一个天然矛盾:你想完全控制位置,但引擎负责自动布局。D2的布局引擎已经很稳,但几十个节点、多条交叉连接时,自动布局不一定符合你想强调的顺序。我的经验是:用容器分组控制大局,用 direction 控制主方向,用节点在文件里的书写顺序微调局部相对位置,强关联节点尽量放进同一个容器。
如果还是差一点,可以尝试给容器增加一些空白或者调整嵌套层级,但不要频繁使用隐藏占位节点来硬拗,容易把图搞乱,后期维护成本反而上升。
5.3 导出PNG模糊、字体缺失
默认PNG是屏幕分辨率,直接放到大屏或者打印会糊。用 --scale 2 甚至 --scale 3,生成高清图。但最推荐的做法还是直接输出SVG,SVG是矢量的,放到网页或者PPT里无论怎么缩放都清晰。字体缺失的问题和中文乱码类似,本质都是渲染环境里没有对应字体,需要把字体文件和渲染脚本绑定在一起,确保CI环境也能找到字体。
5.4 团队不配合怎么办
这是好工具落地时最现实的阻力。我见过很多优秀工具最后死于“只有我一个人在用”。推荐的做法是分三步推进:第一,先把最关键的一张架构图用D2重画,然后以SVG形式嵌入到团队文档站,让所有人先看到效果;第二,在CI里把渲染步骤跑起来,每次代码变更自动重新出图,同事不需要自己安装D2也能拿到最新图;第三,给核心维护者留一份精简的README,告诉新人“只需要改d2源文件,提交后图片会自动更新”。这样比生硬地要求所有人立刻学一门新工具,成功率高得多。
5.5 巨型图性能问题
D2不是不能画大图,几千个节点也能画,但渲染速度和结果可读性都会变差。架构图不等于全量拓扑图,画到能表达关键关系就够了。系统特别大的时候,建议拆分成多个子图,再通过容器嵌套或者文档组织方式把它们组合起来。我一般会按领域边界拆:订单域一张、支付域一张、基础设施一张,最后用总览图引用它们,层级清晰,维护成本也低。
6. 我的个人经验总结
6.1 适合用D2的场景
从我的实际使用来看,D2最适合软件架构图、系统部署图、网络拓扑图、微服务依赖关系图这一类“结构稳定、关系明确、需要持续演进”的图。它也非常适合放在技术文档、在线Wiki、代码仓库里,因为文本格式天然支持diff和review。团队如果已经在做基础设施即代码、文档即代码,那D2的融入几乎是无缝的。
6.2 不太适合的场景
也不是所有图都适合D2。需要像素级自由排版的市场宣传图、示意图,D2不是合适工具;复杂甘特图、时间线类项目计划表,D2的定位不在那儿;如果你的团队必须用严格的BPMN标准建模,D2也不会是首选。Visio在Office生态、自由画布、精细排版这些场景下依然有不可替代的价值,我的建议是:不要抱着“取代一切”的心态,而是把它放进正确的工具箱。
6.3 一点扩展玩法
如果你已经开始用D2,我建议多试试SVG嵌入方案。D2生成的SVG可以直接放进网页,配合CSS做明暗主题适配,甚至可以由脚本在渲染后批量替换品牌颜色。这等于把架构图做成了代码仓库里的一个组件,跟着版本走、跟着测试走、跟着发布流程走,已经超出了“画图工具”的范畴。我个人在实际项目里的体会是,D2带来的不只是效率提升,更多是让架构图从“静态文档”变成了“活代码”。这个观念转变,可能比工具本身更有价值。