
时序图要表达的只有一件事:多个参与者之间,消息按什么顺序来回传递。横轴是参与者,纵轴是时间,从上往下读。
实际画的时候出错位置高度集中在四处:返回消息用了实线箭头、分支直接拿箭头绕过去、激活条随手拉到底、参与者一口气排了十几个。这四个解决掉,图就基本可用了。
一、先分清两种"时序图"
搜"时序图"会撞到两个完全不同的东西:
| UML 时序图 | 硬件时序图 | |
|---|---|---|
| 英文 | Sequence Diagram | Timing Diagram |
| 用在哪 | 软件设计、接口联调、系统交互 | 数字电路、通信协议、芯片手册 |
| 横轴 | 参与者(对象、服务、角色) | 时间 |
| 纵轴 | 时间(从上往下) | 信号电平 |
| 画什么 | 谁向谁发了什么消息 | 信号在什么时刻翻转 |
本文讲的是第一种,UML 时序图。要画时钟、片选、数据线之间的电平配合,那属于硬件时序图,用波形工具,符号完全不是一套。
二、五个基本元素
时序图符号很少,核心五个:
- 参与者(Participant)——顶部方框,代表一个对象、服务、模块或角色。外部使用者用人形图标,内部组件用方框
- 生命线(Lifeline)——参与者往下延伸的竖直虚线,代表它在时间轴上的存在期,只表示"还活着"不表示"在干活"
- 激活条(Activation Bar)——生命线上的窄矩形,也叫执行规格,表示参与者正在处理某件事。收到消息开始,处理完返回结束
- 消息(Message)——参与者之间的水平箭头,写上方法名或动作名,是时序图的主体
- 销毁标记——生命线末端的叉号,表示对象在此销毁。业务时序图通常用不上
激活条是最常被画错的元素。 常见错误是从顶画到底,好像这个参与者全程在工作。正确画法是只覆盖它真正处理请求的那一段,发出消息后等待的时间不算——激活条的长短本身就是信息,能看出哪个服务扛了最长的同步等待。
三、四类消息,线型不能混
线型和箭头样式有严格约定,画错会导致误读:
| 消息类型 | 线型 | 箭头 | 含义 |
|---|---|---|---|
| 同步消息 | 实线 | 实心箭头 | 发出后阻塞等待返回 |
| 异步消息 | 实线 | 开放箭头 | 发出后立即继续,不等 |
| 返回消息 | 虚线 | 开放箭头 | 调用的返回值 |
| 自调用 | 实线折回自身 | 实心箭头 | 参与者调自己的方法 |
同步和异步的区别是整张图里信息量最大的地方。 实心箭头意味着调用方停在那儿等,这段时间什么都干不了;开放箭头意味着发完就走。把异步画成同步,读图的人会以为这里有阻塞等待,进而做出错误的性能判断。
返回消息必须用虚线。 这是最高频的错误——返回画成实线,图上就出现一对方向相反的实线箭头,看起来像两次独立调用,实际是一次调用的一来一回。另外不是每个返回都要画:同步调用的返回是隐含的,只有返回值携带关键信息时才画,否则图会被返回箭头塞满。
四、组合片段:把分支和循环画进去
时序图最大的短板是表达不了分支——纯消息箭头只能走一条固定路径。组合片段就是为此设计的:带标签的矩形框圈住若干条消息,标签说明执行规则。

常用六种,前三种能覆盖九成场景:
- alt——互斥分支。框内用水平虚线分段,每段左上角写条件,相当于 if-else
- opt——可选执行。条件满足才执行框内内容,相当于没有 else 的 if
- loop——循环。标签里写循环条件或次数,如
loop [每个订单项] - par——并行。框内分段同时执行,段间顺序不确定
- break——中断。条件满足时执行框内内容并终止外层剩余部分
- ref——引用另一张时序图,用来把复杂子流程拆出去
组合片段可以嵌套,但不要超过两层。 三层嵌套基本没人能读,那说明这段交互的分支太多,应该拆成主图加子图,用 ref 串起来。
五、时序图和流程图,什么时候用哪个
| 时序图 | 流程图 | |
|---|---|---|
| 主角 | 参与者之间的交互 | 步骤之间的流转 |
| 强项 | 谁调谁、调用顺序、同步还是异步 | 判断条件、分支路径、循环 |
| 弱项 | 复杂分支要靠组合片段,画多了很乱 | 看不出有几个参与者、谁调用谁 |
| 典型场景 | 接口联调、登录鉴权、支付回调 | 审批流程、算法逻辑、业务办理 |
判断方法:核心是"这件事要经过谁、按什么顺序传递"就画时序图;核心是"在什么条件下走哪条路"就画流程图。
还有第三个常被忽略的选项:参与者是部门或岗位、关注职责边界和交接点时,泳道图更合适——它能同时表达参与者和分支,只是不擅长同步等待。
六、画时序图的五步顺序
第一步,确定边界。 一张图只讲一个场景。把"整个订单系统"画进一张图是最常见的失控起点。
第二步,列参与者,控制在 3 到 6 个。 超了说明边界划大了。从左到右按调用发起顺序排,能让大部分箭头朝右,减少交叉。
第三步,只画主干路径。 先把一切顺利时的调用链画通,不考虑异常和分支。
第四步,加组合片段。 主干通了,再用 alt / opt / loop 补上分支、循环、异常。
第五步,补激活条和返回消息。 放最后——前四步还在调整消息位置,早画会反复改。
七、六个高频错误
- 返回消息画成实线——必须虚线,否则一次调用会被读成两次
- 激活条从头拉到尾——只在真正处理时画,等待期间不画
- 用箭头绕圈表示循环——循环必须用 loop 片段,绕回去的箭头会让人分不清是循环还是回调
- 参与者排了十几个——超过 6 个就拆图,用 ref 引用子图
- 消息名写成"数据"或"信息"——要写具体动作或接口名,如"查询库存(skuId)"
- 抽象层级混用——一张图里要么全是业务服务(订单服务、库存服务),要么全是代码组件(Controller、Service、Mapper)
最后一条值得多说一句。 层级混画,读图的人无法判断这张图在描述系统架构还是代码调用,误解就是这么产生的。
八、用文本语法快速出图
时序图结构高度规则,是最适合用文本生成的图种之一。Mermaid 的 sequenceDiagram 几行就能出图:
sequenceDiagram
participant U as 用户
participant O as 订单服务
participant S as 库存服务
U->>O: 提交订单
O->>+S: 校验库存(skuId)
S-->>-O: 剩余库存数
alt 库存充足
O-->>U: 创建成功,返回订单号
else 库存不足
O-->>U: 下单失败,提示缺货
end
记忆点:->> 是实线箭头,-->> 是虚线返回,消息末尾的 + 和 - 分别是激活条的开始和结束,alt / else / end 就是 alt 组合片段。

文本语法的好处是版本可比对、改得快;缺点是排版不可控,节点位置、配色、留白都调不了。所以实际工作流通常两段式:先用文本把结构写对,再导入画布调版式、加注释。英飞·思想家支持把 Mermaid 代码转成可编辑的画布图形,转换后每个元素都能单独拖动和改样式,做法见Mermaid 转图表。
九、什么时候不该画时序图
值得画的:
- 跨系统、跨团队的接口联调,需要双方对齐调用顺序和同步语义
- 涉及回调、重试、超时的异步流程,口头说不清
- 鉴权、支付、对账这类出错代价高、需要留档评审的链路
不值得画的:
判断标准:这段交互有没有被口头讲错过? 讲错过或需要多方书面确认,就值得画。
常见问题
时序图和流程图有什么区别?
时序图的主角是参与者之间的消息传递,强项是调用顺序和同步/异步语义;流程图的主角是步骤流转,强项是判断条件和分支路径。
返回消息为什么必须用虚线?
实线表示一次新调用,虚线表示上一次调用的返回。返回画成实线,图上会出现一对方向相反的实线箭头,读起来像两次独立调用。
时序图里的分支怎么画?
用 alt 组合片段——矩形框圈住相关消息,框内用水平虚线分段,每段左上角写条件。不要用箭头绕圈表示分支或循环。
一张时序图最多画几个参与者?
建议 3 到 6 个。超过 6 个图会宽到读不完,说明边界划得太大,应该拆图并用 ref 互相引用。
激活条应该画多长?
只覆盖参与者真正处理请求的那一段,从收到消息开始到处理完返回结束。等待时间不画——激活条长短本身就在表达哪里有同步阻塞。
结语
时序图能表达两件别的图表达不了的事:调用的先后顺序,以及每次调用是同步还是异步。这两件事讲清楚,接口联调时的大部分误解就消失了。
守住四条:返回用虚线、激活条只覆盖处理期、分支用组合片段不用绕箭头、参与者控制在 6 个以内。先用文本把结构写对,再进画布调版式,比一开始手工拖拽快得多。