时序图栏目 ·

时序图是什么?(UML 序列图)3 分钟搞懂:适用场景、核心元素、常见误解

时序图(Sequence Diagram)是用“时间顺序”把对象之间的交互消息画出来的 UML 图。本文用最短路径讲清:时序图适合解决什么问题、有哪些核心元素、最常见的误解是什么,以及如何快速画出可交付版本。

很多人第一次听到“时序图/序列图”,脑子里会冒出两个疑问:

  1. 我已经会画流程图了,为什么还要学时序图?
  2. 时序图到底要画到多细?是不是要把每个函数调用都画出来?

结论先说在前面:时序图不是用来画“步骤”,而是用来画“交互”。当你想把“谁先调用谁、调用的顺序如何、哪里会等待返回、哪里会异步回调、失败时怎么走”讲清楚时,时序图比流程图更合适。

如果你想边看边画,或者把一段文字交互快速变成专业、美观、可导出的时序图,你可以用这个在线工具(支持自动排版、实时预览、导出 SVG/PNG/JPEG/draw.io,也支持 AI 生成):

下面用“3分钟能看懂”的方式,把时序图讲清楚。


1)时序图是什么?一句话定义

时序图(Sequence Diagram),也叫序列图,是 UML 的一种交互图,用来描述多个对象(参与者)之间按时间顺序发生的消息交互。

你可以把它理解成:

  • 横向:有哪些参与者(用户、客户端、服务端、数据库、第三方服务、消息队列……)
  • 纵向:时间从上往下走
  • 箭头:谁给谁发了什么消息(同步/异步/返回)

它的价值不是“把流程画出来”,而是把交互的顺序、等待关系、分支与异常画清楚。


2)时序图最适合解决什么问题?(5 个典型场景)

下面这些场景,如果你只用流程图描述,往往会越画越别扭;换成时序图,反而一眼清楚。

场景 A:登录/注册(验证码、风控、失败重试)

登录流程看起来是“步骤”,但真正容易出问题的是交互:

  • 前端什么时候发请求?
  • 服务端什么时候查库?
  • 是否要调用风控服务?
  • 失败后是返回错误还是触发二次校验?

这些在时序图里更好表达。

场景 B:下单-支付-回调(同步 + 异步混合)

支付系统典型特点:

  • 下单通常是同步请求
  • 支付结果往往通过异步回调通知
  • 回调可能重复、可能延迟

如果你不把同步/异步、等待/不等待画出来,评审时一定会吵。

场景 C:接口调用链路(超时、重试、降级、熔断)

研发同学写“接口时序图”,通常不是为了好看,而是为了:

  • 对齐调用顺序
  • 标出超时点
  • 说明重试策略
  • 解释失败时如何兜底

场景 D:回调/Webhook(签名校验、幂等、补偿)

回调类流程最容易出线上事故:重复回调、顺序不一致、签名不对、幂等没做好。时序图能把这些关键判断点固定下来。

场景 E:多人协作的技术文档/评审交付

当你要把方案交付给别的团队,或者写进文档/PPT 时:

  • 流程图更像“业务步骤”
  • 时序图更像“接口与交互合同”

这两者不是互斥,而是各自负责不同层面的清晰。


3)时序图的核心元素有哪些?(别背全套,先掌握 6 个就够)

很多人觉得时序图难,是因为一上来就被 UML 名词吓到。其实入门只要先掌握 6 个概念。

3.1 参与者(Actor / Participant)

参与者可以是人(用户/管理员),也可以是系统组件(前端、服务、数据库、第三方)。

经验:参与者不要贪多。 如果你为了“完整”把每个内部模块都画上,图会变成毛线团。

一个可操作的标准:

  • 评审级:参与者保持在 4–7 个
  • 研发链路级:可以更多,但要拆图

3.2 生命线(Lifeline)

每个参与者下面那条竖虚线就是生命线,表示它在这段交互里“存在”。

很多人的误区是把生命线当成“线程/进程”,然后开始纠结长度。入门阶段你只要记住:生命线主要用于承载消息箭头和激活条。

3.3 消息(Message):同步、异步、返回

这是时序图的灵魂。

  • 同步消息:发送方发出后要等结果(常见:HTTP/RPC调用)
  • 异步消息:发送方发出后不等待(常见:消息队列、事件通知)
  • 返回消息:接收方处理完返回结果(不一定每次都要画,后面会讲)

画图时最重要的是:你要让读者看出“有没有等待”

3.4 激活条(Activation)

生命线上的细长矩形表示“正在执行/占用”的时间段。

激活条不一定要画得很细,但它在两类场景非常有价值:

  • 你要表达“谁在等待谁”
  • 你要表达“嵌套调用”(例如服务 A 调用服务 B,B 又调用 C)

3.5 自调用(Self-call)

一个参与者调用自己,常用于表达:内部方法调用、递归、内部处理。

注意:自调用不是用来替代流程图的。如果你把所有内部步骤都画成自调用,时序图会失去重点。

3.6 组合片段(Combined Fragment):alt/opt/loop/par

这是让时序图从“线性对话”升级成“可表达真实世界”的关键。

  • alt:分支(if-else)
  • opt:可选分支(if 条件成立才发生)
  • loop:循环(重试、分页、重复请求)
  • par:并行(要谨慎使用,容易误导)

如果你只会画主干,不会画分支,那么你的时序图往往“看起来对,但不能交付”。


4)最常见的 6 个误解(把这些避开,你的时序图会立刻变专业)

误解 1:时序图 = 流程图

流程图回答“先做什么再做什么”,时序图回答“谁先调用谁”。

当你关心的是“交互合同”(接口、回调、等待、异常)时,优先画时序图。

误解 2:时序图要画到“每个函数”

大多数情况下不需要。

更实用的做法是:

  • 先画到“服务/系统/外部依赖”层级
  • 真正复杂的一段再单独拆出子图

误解 3:返回消息必须每条都画

如果每个同步调用都画返回,你的图会立刻变长、变乱。

返回消息建议只在两种情况画:

  • 返回值影响后续分支(例如:校验通过/失败)
  • 你要表达性能/等待关系(例如:超时点)

误解 4:分支只要写“成功/失败”就够了

这会让读者不知道失败后怎么办。

更可交付的做法是把失败按原因拆 2–3 类(例如:参数非法/无权限/超时),让每条分支都有信息量。

误解 5:并行用 par 随便画

par 表示并行执行,但很多业务上的“看起来同时”其实是:

  • 异步事件(用异步消息更合适)
  • 或者只是“先后顺序不重要”(可以用注释,不一定要 par)

误解 6:对象命名随意

评审时最常见的扯皮之一就是:同一个东西在图里被叫了三个名字。

建议:

  • 参与者命名尽量统一为“角色/系统名”
  • 消息命名尽量用“动词+对象”(例如:查询订单、校验签名、创建支付单)

5)如何快速画出一张“可交付”的时序图?(不靠手动排版)

如果你现在要把一段交互写进文档或做评审,建议用下面这个“最小可交付”流程:

  1. 先确定 4–7 个参与者(别贪多)
  2. 先画主干消息(只画关键交互)
  3. 把关键分支用 alt/opt/loop 表达出来(不要只写成功/失败)
  4. 再决定哪些返回消息需要画(影响分支的才画)
  5. 最后导出:
    • 写文档/论文:优先 SVG(放大不糊)
    • PPT/截图:高清 PNG/JPEG
    • 交给同事继续编辑:导出 draw.io

如果你想用“点一点 + 输入文本”就把这些做完,并且自动排版、右侧实时预览,可以直接打开:


FAQ

Q1:时序图、序列图、UML时序图是不是同一个东西?

大多数情况下可以当作同一个概念使用。更严格的说法是:时序图/序列图是图的类型,UML 是规范体系;当你按 UML 语义画(消息类型、片段语义更规范)时,就可以叫 UML 时序图。

Q2:参与者里要不要画数据库?

看你的目的:

  • 评审业务/接口:画到“服务”层就够了,数据库可以省略
  • 你要表达一致性、事务、补偿:数据库/缓存/消息队列就应该出现

Q3:我应该先画时序图还是先画流程图?

如果你在梳理业务步骤,先画流程图;如果你在梳理系统交互与接口合同,先画时序图。

很多高质量文档会两张都画:流程图讲步骤,时序图讲交互。


6)一个“真实可评审”的小案例:用户登录(含验证码与风控)该怎么画?

很多教程讲时序图会停在“概念层”,但真正让评审不扯皮的,是你能不能把关键交互和分支画出来。

下面用“登录”举一个更贴近真实系统的拆解。你不需要照抄这套流程,重点是看它如何把同步/异步、分支条件、失败处理表达清楚。

6.1 参与者怎么选(别一上来就画 10 个)

建议先选到“能说清楚责任边界”的层级:

  • 用户(或客户端)
  • 前端(Web/App)
  • 认证服务(Auth)
  • 风控服务(Risk)
  • 用户服务/用户库(User)
  • 短信服务(SMS)

如果你只是做作业/写概要文档,也可以把 User+DB 合并成一个“用户系统”。

6.2 主干交互(先把大链路跑通)

主干消息可以按这个顺序组织:

  1. 用户 → 前端:输入手机号
  2. 前端 → Auth:请求发送验证码
  3. Auth → Risk:检查频控/黑名单
  4. Risk → Auth:允许/拒绝
  5. Auth → SMS:发送验证码
  6. SMS → Auth:发送结果(可选画返回)
  7. 用户 → 前端:输入验证码
  8. 前端 → Auth:提交验证码
  9. Auth → User:校验用户/创建登录态
  10. Auth → 前端:返回 token/会话

这段里至少要把“Risk 检查”画出来,否则登录图会显得过于理想化。

6.3 必画的分支(否则“成功/失败”毫无信息量)

建议用组合片段把分支按“读者关心”组织,而不是按“程序分支”组织。

分支 A:风控拒绝(alt)

  • 条件示例:命中黑名单 / 频控触发 / 设备指纹异常
  • 后续处理:提示稍后再试 / 触发图形验证码 / 转人工

分支 B:短信发送失败(alt)

  • 条件示例:运营商通道异常 / 配额不足 / 参数不合法
  • 后续处理:提示失败 + 允许重发(loop)

分支 C:验证码错误/过期(alt + loop)

  • 错误:允许重输,但要限制次数
  • 过期:要求重新发送

为什么要把“错误”和“过期”分开?因为它们对用户体验与风控策略不同。

6.4 重试(loop)要写什么才算可交付?

很多人画 loop 只写“重试”,但评审时会被追问:

  • 重试几次?
  • 触发条件是什么?
  • 间隔多久?

你不必写到实现细节,但至少给一个可评审的边界,例如:

  • 仅对“短信通道异常/网络超时”重试
  • 最多 3 次
  • 60 秒内超过次数触发图形验证码

把这些写在 loop 的标签里,图就从“概念图”变成“能落地的方案图”。


7)导出与交付:SVG / PNG / draw.io 分别什么时候用?

你工具支持导出 SVG、PNG/JPEG、draw.io,这一点对“把图放进文档/PPT/交接”非常关键。

7.1 导出 SVG:适合文档与论文(放大不糊)

如果你的时序图会被放进:

  • 技术文档(Markdown/网页)
  • 论文/报告
  • 需要多次缩放的场景

优先选 SVG。

7.2 导出 PNG/JPEG:适合 PPT 与截图

PPT 里最常见的问题是“放大后发虚”。解决思路不是换格式,而是:

  • 导出更高分辨率
  • 控制单张图的信息量(复杂就拆图)

7.3 导出 draw.io:适合交接与二次编辑

如果你要把图交给同事继续改,或者后续还会频繁调整布局,导出 draw.io 会更省时间。

你可以把它当作“交付源文件”,而不是只交付一张图片。


8)再强调一次:时序图画得好,关键是“分支与异常”

很多人画时序图只画主干,最后在图旁边写一行“失败则返回错误”。这几乎等于没画。

你可以用一个很简单的自检:

  • 这张图里有没有明确的 alt/opt/loop?
  • 失败分支是不是有“下一步动作”(提示/重试/转人工/补偿)?
  • 是否能据此写出 5 条测试用例?

如果答案都是“能”,这张图基本就能拿去评审。

想把一段文字交互快速落到图上(不手动排版、点选生命线/消息/片段、右侧实时预览),可以直接打开:


9)常见问法速答:你可能会搜的 12 个问题

为了让你在查资料时少走弯路,这里把“新手最常搜、最常问”的问题集中回答一下。

Q1:时序图一定要画激活条吗?

不一定。

  • 如果你只是在对齐“谁调用谁”的顺序,可以不画激活条。
  • 如果你要表达等待关系、嵌套调用、性能瓶颈,激活条会非常有用。

一个简单判断:你是否需要解释“谁在等谁”? 需要就画。

Q2:参与者该用“用户/前端/后端”,还是用“具体服务名”?

取决于读者是谁:

  • 面向业务/产品评审:用“前端/订单服务/支付服务”这种可理解的名字
  • 面向研发实现:用“OrderService/PayGateway/InventoryService”更直接

但无论哪种,最重要的是:同一张图里不要一会儿“支付系统”,一会儿“PaySrv”,会让读者以为是两个东西。

Q3:消息命名有什么规范?

推荐“动词 + 对象”或“动作 + 结果”的写法:

  • 创建订单
  • 查询库存
  • 校验签名
  • 更新支付状态

不推荐“请求/处理/调用”这种空词。

Q4:返回消息到底画不画?

只在两种场景强烈建议画:

  1. 返回值会影响分支(通过/失败)
  2. 你要强调等待与耗时(例如:超时点)

其他情况可以省略,让图更干净。

Q5:时序图里要不要画缓存/消息队列?

如果它会影响交互语义(异步、延迟、重试、至少一次投递),就应该画。

  • MQ 不画出来,读者会误以为是同步调用
  • 缓存不画出来,读者会误以为每次都查库

Q6:组合片段 alt/opt/loop/par 的条件写在哪里?

条件应该写在片段的标签里(例如 alt 的每个分支条件)。

条件的写法尽量“可验证”,不要写情绪词:

  • 推荐:token 已过期 / 签名校验失败 / 库存不足
  • 不推荐:异常 / 不对 / 有问题

Q7:loop(循环)怎么写才不空泛?

loop 最容易被追问“循环几次”。

建议你至少写三件事中的两件:

  • 次数上限(最多 3 次)
  • 触发条件(仅超时/5xx 重试)
  • 间隔策略(指数退避)

这样才算“可交付”。

Q8:par(并行)是不是很常用?

par 很容易误导读者以为“严格并行”。

在很多业务系统里,并行更多是“异步事件”或“顺序不重要”。如果你不确定,优先用异步消息表达,而不是 par。

Q9:时序图能不能画“业务规则”?

可以,但不要把时序图写成规则百科。

更好的做法是:

  • 规则用条件(alt/opt)表达
  • 规则的详细定义写在旁注或文档里

Q10:时序图怎么保证不画错?

用一个非常实用的自检方法:

  • 把图当成“对话记录”,从上往下读一遍
  • 看看有没有一句话读不通(例如消息缺主语、返回缺来源)
  • 看看有没有“没有下一步动作”的分支

Q11:时序图和接口文档(API 文档)是什么关系?

时序图不是接口文档的替代品,但它能把“接口之间的顺序与依赖”讲清楚。

  • 接口文档回答:字段/错误码/参数
  • 时序图回答:谁先调用谁、失败怎么走、回调怎么处理

Q12:我想快速画,最省时间的方式是什么?

先把参与者和主干消息列出来,再补 2–3 条最关键的异常分支,然后用工具自动排版。

你可以直接用在线编辑器点选生命线/消息/组合片段,右侧实时预览,最后一键导出 SVG/PNG/draw.io: