使用 Python 绘制系统架构设计图
绘制系统架构设计图是技术文档的重要组成部分。随着系统复杂度不断上升,团队内部保持清晰沟通变得越来越关键。
但用画布类的工具从零开始画图,往往效率不高。
好在还有另一种方式:Diagram-as-Code(图即代码)。这种方式下,你不需要动手画,而是用预定义的语法来描述图的各个组件。
目录
Diagram-as-Code 的优势:
改动可以通过版本控制来追踪。
省时省力——手动绘图或调整格式都很耗时。
大多数 diagram-as-code 工具都内置了常见的技术图标,比如数据库、存储桶、负载均衡器等。
可以通过代码在 CI/CD 流水线或文档构建中自动生成图表。
环境准备与安装
本教程将带你使用 Python 的 Diagrams 库来绘制图表。基本环境要求如下:
Python 3.7+
用于安装 Python 包的 pip
操作系统中已安装 Graphviz,用于渲染输出图片
Python 包:
pip install diagrams一个终端,用于运行文件,比如:
python diagram.py
Diagrams 是什么?
Diagrams 是一个 Python 库,让你用 Python 代码绘制云系统架构图。它支持 Azure、GCP、AWS 等多种云服务商。
学完本教程后,你就能理解下面这张图是怎么做出来的:
你的第一个图表
首先,请确认已按前提条件完成环境搭建。然后创建一个 .py 扩展名的 Python 文件,并添加以下代码:
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Practice Architecture"):
EC2("api-server")
让我们逐行理解这段程序。
第一步,导入 Diagram:
from diagrams import Diagram
可以把 Diagram 想象成一块空白画布,你绘制的所有内容都放在其中。Diagram 表示一个全局图表上下文。
接着导入节点类型。节点(node)代表架构中的一个组件。例如,ECS、Lambda、Service 和 Firewall 都是资源类型。
from diagrams.aws.compute import EC2
节点对象由三部分组成:提供商(provider)、资源类型(resource type)和名称(name)。在上面的示例中,EC2 是一个由 aws 提供商提供的、属于 compute 资源类型的节点。
这行代码从 AWS 计算组导入 EC2 节点。我们将使用该类来创建 EC2 节点。
diagrams.aws.compute 是导入路径,它指明了 EC2 图标的所在位置。
diagrams
└── aws
└── compute
└── EC2
你可以在这里探索更多提供商的官方节点类型。
假设你想在图表中使用 AWS 的 Analytics 组件。首先,从上面列出的节点类型清单中搜索 Analytics。你的导入语句应如下所示:from diagrams.aws.analytics import Analytics。
然后使用 with Diagram 创建图表上下文:
with Diagram("Practice Architecture"):
回到你的示例,这创建了一个名为 Practice Architecture 的图表。with Diagram 下方所有缩进的内容都属于该图表。
现在创建一个节点:
EC2("api-server")
这会创建一个 EC2 节点,标签显示在其下方,内容为 api-server。
最后,运行代码。如果你将 Python 文件保存为 test.py,则使用 python test.py 执行。Diagrams 会在当前目录下生成一个图像文件:
简而言之,整个流程如下所示:
请注意,你是在描述基础设施,而不是手动绘制。你不需要思考如何绘制和排列图标,只需编写 EC2("api-server"),Diagrams 就会自动决定渲染方式。
我们可以稍微扩展上述示例,加入两个 EC2 实例:
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Practice Architecture"):
EC2("api-server")
EC2("worker")
注意,你可以将节点实例赋值给变量,这样引用起来会更方便。
下面的示例展示了变量赋值:
from diagrams import Diagram
from diagrams.aws.compute import EC2
with Diagram("Practice Architecture"):
api_server = EC2("api-server")
worker = EC2("worker")
如何连接节点与数据流
你已经学会了如何创建节点,现在来看看如何连接它们。
方向由以下符号表示:
>>表示从左到右的流向<<表示相反方向(从右到左)-表示无方向连接
下面是一个综合示例:
from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB
with Diagram("The three directions"):
load_balancer = ELB("load-balancer")
web_server = EC2("web-server")
database = RDS("database")
backup_server = EC2("backup-server")
load_balancer >> web_server
web_server << database
database - backup_server
注意节点之间的连接方式:
# 用从左到右的箭头连接负载均衡器和 Web 服务器
load_balancer >> web_server
# 用从右到左的箭头连接 Web 服务器和数据库
web_server << database
# 用直线连接数据库和备份服务器
database - backup_server
对数据流进行分组
你还可以借助 Python 列表,把一个节点连接到多个节点,而不必逐个手动连接。
假设你想实现这样的架构:
┌──► web-1 ───┐
load-balancer ──────┼──► web-2 ───┼──► database
└──► web-3 ───┘
先创建负载均衡器:
load_balancer = ELB("entry-point")
然后创建几台服务器。与其像下面这样定义三个独立的变量:
server1 = EC2("web-1")
server2 = EC2("web-2")
server3 = EC2("web-3")
不如把它们放进一个 Python 列表里:
web_servers = [
EC2("web-1"),
EC2("web-2"),
EC2("web-3")
]
接着把 LB 节点连接到这个列表,即 load_balancer >> web_servers:
load_balancer >> web_servers
这样就不用手动写成:
load_balancer >> web_servers[0]
load_balancer >> web_servers[1]
load_balancer >> web_servers[2]
然后把整个列表连接到数据库:
web_servers >> database
这种方式能有效减少代码冗余,适合连接多个 pod、worker 之类的重复组件。
完整代码如下:
from diagrams import Diagram
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
from diagrams.aws.network import ELB
with Diagram("Scaled Web App"):
load_balancer = ELB("entry-point")
web_servers = [
EC2("web-1"),
EC2("web-2"),
EC2("web-3")
]
database = RDS("orders-db")
load_balancer >> web_servers >> database
集群
你可以使用集群将相关节点归入带标签的方框中。集群内的节点仍然可以与外部节点建立连接。
分组有助于展示哪些元素属于同一层级,从而直观表达以下概念:
应用层
数据库层
可用区
区域
环境
微服务组
工作节点组
创建集群的语法如下:
with Cluster("Cluster name"):
该语句下方缩进的所有内容都将成为集群的一部分。
下面是一个演示集群用法的示例:
from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
with Diagram("Shop Platform"):
with Cluster("Application Tier"):
apps = [
EC2("app-1"),
EC2("app-2")
]
with Cluster("Database Tier"):
primary_db = RDS("primary-db")
replica_db = RDS("read-replica")
apps >> primary_db
primary_db - replica_db
还可以使用以下语法嵌套集群:
with Cluster("Production"):
with Cluster("Backend"):
with Cluster("API"):
...
来看一个更贴近实际场景的嵌套集群示例:
from diagrams import Diagram, Cluster
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
with Diagram("Production Platform"):
with Cluster("Production Region"):
with Cluster("Application Tier"):
with Cluster("API Servers"):
api1 = EC2("api-1")
api2 = EC2("api-2")
database = RDS("main-db")
api1 >> database
api2 >> database
此示例展示了一个「Production Platform」,其中包含「Production Region」,而「Production Region」内又包含「Application Tier」。「Application Tier」进一步将两个 API 服务器归为一组。独立的 RDS 数据库位于生产区域内,两个 API 服务器均与其连接。
通过缩进,可以将集群嵌套在其他集群之下。参考下方的代码片段:
with Cluster("Production Region"):
with Cluster("Application Tier"):
with Cluster("API Servers"):
api1 = EC2("api-1")
api2 = EC2("api-2")
Edges
Edges 提供了另一种连接节点的方式。与普通 >> 或 << 不同,Edges 允许你添加标签、颜色和样式等属性。
之前你使用的是:
from diagrams import Diagram
若要使用 Edge,请添加:
from diagrams import Diagram, Edge
现在使用 Edge 将 app 连接到 database:
# Labeling an edge
app >> Edge(label="SQL queries") >> database
这使用带有 "SQL queries" 标签的 Edge 将 app 连接到 database。
你还可以自定义 Edge 的颜色:
app >> Edge(label="SQL", color="red") >> database
你还可以修改线条样式:
app >> Edge(style="dashed") >> database
还有其他可选的边样式:
Edge(style="dotted")
Edge(style="bold")
下面的示例组合使用了多种边样式:
from diagrams import Diagram, Edge
from diagrams.aws.compute import EC2
from diagrams.aws.database import RDS
with Diagram("Payment Service"):
api = EC2("payment-api")
database = RDS("payments-db")
api >> Edge(
label="payment records",
color="darkgreen",
style="dashed"
) >> database
注意,边也可以配合 << 和 - 使用。
结语
通过本教程,你学会了如何用“图表即代码”的方式创建有意义、风格统一且便于团队协作的架构图。这种方式既能保证质量,又不影响其他开发和维护工作,让你事半功倍。
本教程主要使用了 AWS 组件。你可以参考这份指南了解其他可用的云服务提供商,按自己的需求绘制图表。
感谢你读到最后。如果这篇文章对你有帮助,欢迎分享给更多人。
保持联系,继续你的学习之旅!
可以通过以下方式联系我:
祝编码愉快!