PPT 级技术架构图制作:从架构设计到可视化表达的完整工作流 PPT 级技术架构图制作从架构设计到可视化表达的完整工作流一、深度引言与场景痛点大家好我是赵咕咕。做了八年技术我至少画过 200 张架构图。但坦白说前 180 张都是不合格的——不是因为画得不好看而是画的人没想清楚给谁看和看什么。一张架构图给老板看和给开发团队看重点完全不同老板关心整体结构、模块边界、数据流向——三分钟内读懂。开发团队关心技术细节、接口定义、依赖关系——精确到模块级别。运维团队关心部署拓扑、故障转移、监控节点——看的是物理部署。后来我总结了一套工作流先设计架构再映射到图表效果立竿见影。今天把方法分享出来——不是教你怎么用工具画图而是教你怎么把架构思维表达成可视化图形。二、底层机制与原理深度剖析2.1 为什么大多数架构图都不合格常见的三类问题信息过载一张图塞了 50 个组件每个组件都有连线密度太高没人看得懂。架构图不是 ER 图应该控制 15-20 个核心元素。缺少层次所有组件平铺在一层看不出主次关系。好的架构图有清晰的分层用户层 → 网关层 → 业务层 → 数据层。连线混乱箭头没有方向标记、没有标注协议、交叉线太多。架构图的连线不是随便拉的——REST/HTTP 是实线消息队列是虚线数据库连接是点线。2.2 架构图的四层金字塔2.3 架构图绘制的最佳实践十一条左下到右上数据流向从左下输入到右上输出这是人眼阅读习惯。颜色编码不超过 5 种颜色。红色 核心/瓶颈蓝色 服务绿色 存储橙色 中间件灰色 外部依赖。分层标注用虚线框标注层次每层有名称。连线协议标注REST/gRPC/MQ/DB/Redis——每条线标注协议类型。数字标注标注 QPS、延迟、数据量——架构图加数字才有说服力。不要标注所有连线只标注关键数据流配置/监控/日志链路可以省略。留白 30%不要把图画满密集的架构图没人看。统一图标风格全方框或全圆角不要混用不同风格的图标。版本号标注架构图右下角标注日期和版本——架构是演进的。一句话标题图上方用一句话概括这张图在表达什么。Mermaid 优先能用代码画的不用鼠标拖Mermaid 可以版本控制、可以 diff、可以 CI 自动渲染。三、生产级代码实现3.1 用 Python 生成 Mermaid 架构图手写 Mermaid 是可行的但当组件超过 20 个时手动维护很容易出错。更好的方式是用代码生成 Mermaid。import asyncio import logging from dataclasses import dataclass, field from enum import Enum from typing import Any logger logging.getLogger(__name__) class ComponentType(str, Enum): 组件类型。 SERVICE service # 微服务 DATABASE database # 数据库 CACHE cache # 缓存 QUEUE queue # 消息队列 GATEWAY gateway # 网关 EXTERNAL external # 外部系统 STORAGE storage # 对象存储 MONITOR monitor # 监控 USER user # 用户 class ConnectionType(str, Enum): 连接类型。 HTTP http GRPC grpc MQ mq DB db CACHE_CONN cache EVENT event # 组件颜色映射 COLOR_MAP: dict[ComponentType, str] { ComponentType.SERVICE: #4A90D9, ComponentType.DATABASE: #2ECC71, ComponentType.CACHE: #E74C3C, ComponentType.QUEUE: #F39C12, ComponentType.GATEWAY: #9B59B6, ComponentType.EXTERNAL: #95A5A6, ComponentType.STORAGE: #1ABC9C, ComponentType.MONITOR: #E67E22, ComponentType.USER: #3498DB, } # 连线样式映射 CONNECTION_STYLE: dict[ConnectionType, str] { ConnectionType.HTTP: --, ConnectionType.GRPC: , ConnectionType.MQ: -.-, ConnectionType.DB: --o, ConnectionType.CACHE_CONN: ..-, ConnectionType.EVENT: -.-, } dataclass class Component: 架构组件。 name: str label: str comp_type: ComponentType layer: str description: str tech_stack: list[str] field(default_factorylist) dataclass class Connection: 组件间连接。 source: str target: str conn_type: ConnectionType label: str bidirectional: bool False protocol: str # e.g., REST, gRPC, Kafka class ArchitectureDiagram: 架构图生成器。 支持生成 - Mermaid flowchart逻辑架构图 - Mermaid C4 Context系统上下文图 def __init__(self, title: str, version: str v1.0): self._title title self._version version self._components: dict[str, Component] {} self._connections: list[Connection] [] self._layers: dict[str, list[str]] {} def add_component(self, comp: Component) - None: 添加组件。 self._components[comp.name] comp if comp.layer: if comp.layer not in self._layers: self._layers[comp.layer] [] self._layers[comp.layer].append(comp.name) def add_connection(self, conn: Connection) - None: 添加连接。 # 验证源和目标组件是否存在 if conn.source not in self._components: logger.warning(源组件不存在: %s, conn.source) if conn.target not in self._components: logger.warning(目标组件不存在: %s, conn.target) self._connections.append(conn) def build_mermaid(self) - str: 构建 Mermaid flowchart 代码。 lines [ mermaid, flowchart TB, ] # 分层 if self._layers: for layer_name, comp_names in self._layers.items(): safe_name layer_name.replace( , _) lines.append(f subgraph {safe_name}[\{layer_name}\]) for name in comp_names: comp self._components[name] color COLOR_MAP.get(comp.comp_type, #AAAAAA) lines.append( f {name}[\{comp.label} ) if comp.tech_stack: tech , .join(comp.tech_stack[:3]) lines[-1] fbr/small{tech}/small lines[-1] f\] lines.append(f style {name} fill:{color},color:#fff) lines.append( end) lines.append() else: # 无分层直接列出组件 for name, comp in self._components.items(): color COLOR_MAP.get(comp.comp_type, #AAAAAA) lines.append(f {name}[\{comp.label}\]) lines.append(f style {name} fill:{color},color:#fff) # 连接 for conn in self._connections: style CONNECTION_STYLE.get(conn.conn_type, --) label f|{conn.label}| if conn.label else protocol fbr/{conn.protocol} if conn.protocol else if conn.bidirectional: lines.append( f {conn.source} {style}{label} {conn.target} ) lines.append( f {conn.target} {style} {conn.source} ) else: lines.append( f {conn.source} {style}{label} {conn.target} ) # 版本标注 lines.append() lines.append( f %% {self._title} | {self._version} | fGenerated by ArchitectureDiagram ) lines.append() return \n.join(lines) def build_c4_context(self) - str: 构建 C4 系统上下文图简化版。 lines [ mermaid, C4Context, f title {self._title}, ] # 用户 users [ c for c in self._components.values() if c.comp_type ComponentType.USER ] for user in users: lines.append( f Person({user.name}, \{user.label}\) ) # 系统 services [ c for c in self._components.values() if c.comp_type ComponentType.SERVICE ] for svc in services: lines.append( f System({svc.name}, \{svc.label}\) ) # 外部系统 externals [ c for c in self._components.values() if c.comp_type ComponentType.EXTERNAL ] for ext in externals: lines.append( f System_Ext({ext.name}, \{ext.label}\) ) # 关系 for conn in self._connections: label conn.label or conn.conn_type.value lines.append( f Rel({conn.source}, {conn.target}, \{label}\) ) lines.append() return \n.join(lines) def build_sequence(self, title: str, steps: list[dict[str, str]]) - str: 构建时序图。 lines [ mermaid, sequenceDiagram, f title {title}, ] participants set() for step in steps: participants.add(step[from]) participants.add(step[to]) for p in sorted(participants): lines.append(f participant {p}) lines.append() for step in steps: from_p step[from] to_p step[to] msg step[message] arrow step.get(arrow, -) lines.append(f {from_p} {arrow} {to_p}: {msg}) lines.append() return \n.join(lines) def build_er_diagram(self, tables: list[dict[str, Any]]) - str: 构建 ER 图。 lines [ mermaid, erDiagram, ] for table in tables: name table[name] lines.append(f {name} {{) for col in table.get(columns, []): col_type col.get(type, string) col_key if col.get(primary_key): col_key PK elif col.get(foreign_key): col_key FK lines.append( f {col_type} {col[name]}{col_key} ) lines.append( }) lines.append() # 关系 for table in tables: for rel in table.get(relations, []): lines.append( f {table[name]} ||--o{{ {rel[target]} : \{rel.get(label, )}\ ) lines.append() return \n.join(lines) def save(self, filepath: str, diagram_type: str flowchart) - None: 保存 Mermaid 图到文件。 if diagram_type flowchart: content self.build_mermaid() elif diagram_type c4: content self.build_c4_context() else: content self.build_mermaid() from pathlib import Path Path(filepath).parent.mkdir(parentsTrue, exist_okTrue) Path(filepath).write_text(content, encodingutf-8) logger.info(架构图已保存: %s, filepath) # ─── 使用示例构建 RAG 服务架构图 ─── async def main(): diagram ArchitectureDiagram( titleRAG 检索增强生成服务架构, versionv2.3.0, ) # 添加组件 diagram.add_component(Component( nameuser, label用户, comp_typeComponentType.USER, layer用户层, )) diagram.add_component(Component( namegateway, labelAPI Gateway\nKong/Nginx, comp_typeComponentType.GATEWAY, layer接入层, tech_stack[Kong, Nginx], )) diagram.add_component(Component( namerag_service, labelRAG 检索服务\nFastAPI, comp_typeComponentType.SERVICE, layer业务层, tech_stack[FastAPI, Python 3.11, asyncio], )) diagram.add_component(Component( nameembedding, labelEmbedding 服务\nvLLM, comp_typeComponentType.SERVICE, layer业务层, tech_stack[vLLM, bge-large-zh], )) diagram.add_component(Component( nameredis, labelRedis\n缓存 向量, comp_typeComponentType.CACHE, layer数据层, tech_stack[Redis Stack], )) diagram.add_component(Component( namemilvus, labelMilvus\n向量数据库, comp_typeComponentType.DATABASE, layer数据层, tech_stack[Milvus 2.4], )) diagram.add_component(Component( namellm_api, labelLLM API\nGPT-4o, comp_typeComponentType.EXTERNAL, layer外部依赖, tech_stack[OpenAI], )) # 添加连接 diagram.add_connection(Connection( sourceuser, targetgateway, conn_typeConnectionType.HTTP, protocolHTTPS, )) diagram.add_connection(Connection( sourcegateway, targetrag_service, conn_typeConnectionType.HTTP, protocolREST, )) diagram.add_connection(Connection( sourcerag_service, targetembedding, conn_typeConnectionType.GRPC, protocolgRPC, label文本→向量, )) diagram.add_connection(Connection( sourcerag_service, targetredis, conn_typeConnectionType.CACHE_CONN, protocolRedis, label查询缓存, )) diagram.add_connection(Connection( sourcerag_service, targetmilvus, conn_typeConnectionType.DB, protocolgRPC, label向量检索, )) diagram.add_connection(Connection( sourcerag_service, targetllm_api, conn_typeConnectionType.HTTP, protocolHTTPS, label生成回答, )) # 保存 diagram.save(/tmp/rag_architecture.md, flowchart) # 也可以生成 C4 图 diagram.save(/tmp/rag_c4.md, c4) # 打印 Mermaid 代码 print(diagram.build_mermaid()) if __name__ __main__: asyncio.run(main())代码的关键设计组件 连接模型用Component和Connection两类数据结构描述架构然后渲染为 Mermaid。这比直接在 Mermaid 里写更容易维护而且可以从同一个数据模型生成多种图表flowchart、C4、时序图。颜色编码自动化组件类型自动映射颜色。数据库永远是绿色缓存永远是红色——不需要每次手动选颜色。连线样式自动化连接类型自动映射 Mermaid 箭头样式。HTTP 用实线箭头--消息队列用虚线-.-一目了然。分层支持_layers字典将组件分组到不同的 subgraph 中自动生成分层结构。多图导出同一份架构数据可以导出为 flowchart、C4、时序图、ER 图。四、边界分析与架构权衡4.1 用代码生成架构图 vs 手画方法优点缺点适用场景手画Draw.io/Figma自由度高好看不可版本管理不可自动化一次性汇报不需要更新Mermaid 手写版本管理diffable手动维护组件多时容易乱小团队组件 20代码生成 Mermaid自动化数据驱动灵活性受限大项目架构频繁变更PlantUML功能强语法复杂需要 C4 标准图推荐组合代码生成 Mermaid。架构数据从 CMDB 或配置文件中来每次变更自动更新架构图。避免架构图跟不上代码的老问题。4.2 架构图的版本管理架构图和代码一样需要版本管理。建议Mermaid 源文件放在 Git 仓库的docs/architecture/目录。CI 自动渲染为 PNG/SVG附在 Release Notes 中。每次架构变更 PR 必须更新对应的架构图。4.3 给不同受众的不同视角受众图表类型关键数据CTO/VPC4 系统上下文图系统边界 数据流向Tech Lead逻辑架构图模块划分 接口开发团队时序图 API 文档调用流程 参数SRE/运维部署拓扑图故障转移 监控数据团队数据流图ETL 存储4.4 Mermaid 的局限性Mermaid 不适合的场景需要精确位置的图Mermaid 是自动布局需要大量自定义图标的图需要拖拽交互的图商业级别的精美图表建议用 Draw.io 或 Lucidchart但 Mermaid 在版本管理 自动化 快速迭代这三个维度上是无可替代的。五、总结架构图绘制不是画图技能问题是架构思维的可视化表达能力问题。核心方法论先分层再填充一张好的架构图自上而下至少有 3-4 个清晰的逻辑层。用代码管理架构图Mermaid Python 代码生成把架构图纳入 Git 版本管理。颜色和连线有语义不是随机选颜色——红色 瓶颈绿色 存储虚线 异步。给不同受众画不同的图老板看大局开发看接口运维看拓扑。架构图是活的架构在演进图必须跟随更新。做到代码变了图自动变是终极目标。一张好的架构图能让新成员 10 分钟内理解系统能让老板 3 分钟内做出技术决策能让运维 1 分钟内定位故障。这不是画图的问题是沟通效率的问题。下一篇预告Agent 商业化的五个坑——技术之外还需要考虑的合规、成本和用户。