全链路追踪
约 1655 字大约 6 分钟
2025-03-03
系统规模一旦上来,最让人头疼的往往不是“报错了”,而是“我知道它出了问题,但我不知道问题是在哪一段出的”。
对于一个同时包含 HTTP、RPC、消息队列、MQTT、数据库、设备上下行的系统来说,如果链路追踪做得不好,排障就会迅速退化成猜谜游戏。
联犀当前的全链路追踪,核心目标不是堆更多日志,而是把一次请求真正串起来。
为什么默认 tracing 还不够
现代框架通常都会帮你把 API 和 RPC 链路的 tracing 基础打好。
go-zero 也已经把这一层做得比较完整。
但真正到业务里,光有 API 和 RPC span 还是不够,至少还缺下面几段:
- 消息队列里的上下文传递
- 数据库日志中的业务定位
- 设备侧请求与平台内部链路的关联
如果这几段断掉了,你看到的就只是一串分散的日志片段,而不是一条完整业务链。
联犀当前重点补的是哪几段
联犀当前主要补了三类 tracing 空白:
- SQL 日志
- 消息总线
- 设备消息
它们恰好覆盖了大部分平台里最容易断链的地方。
SQL 链路:不只是打印 SQL
很多系统说“我们支持 SQL tracing”,最后只是把 SQL 文本和耗时打印出来。
这当然有帮助,但还不够。
真正排障时,开发者最关心的通常是:
- 这条 SQL 慢不慢?
- 它影响了多少行?
- 它是从哪段业务逻辑触发出来的?
联犀当前在 GORM logger 上做的增强,重点就是最后一项。
除了常规的 SQL、耗时、行数,还会尽量把业务层调用位置一起打出来。
这件事看起来只是多一个字段,但意义非常大。
因为在复杂系统里,你真正想看到的不是 ORM 内部调用栈,而是:
“这条慢 SQL 是哪个逻辑文件、哪一行触发的?”
一旦这点补上,排查路径会短很多。
为什么消息总线一定要封装
异步消息链路最常见的问题是:
发送端和消费端都各自有日志,但上下文已经断了。
这类问题在 NATS、MQTT 等消息总线场景里尤其明显。
如果消息里只放业务 payload,那消费方根本不知道:
- 这条消息属于哪次请求
- 谁触发了它
- 它跟前面的 API 或 RPC 调用是什么关系
联犀当前的做法是,所有消息尽量先经过统一消息头封装,再发到总线上。
消息头里会带上:
- trace 信息
- 时间戳
- 原始数据
- 用户上下文
这样做以后,消费端就可以恢复出远端 span context,并继续在同一条逻辑链上记录日志。
这一步非常关键。
因为异步消息一旦不传上下文,整条链路在“发送成功”那一刻就断开了。
为什么还要传用户上下文
只有 traceID 也不够。
很多业务排障时,不只是要知道“哪个请求”,还要知道:
- 哪个用户触发的
- 属于哪个租户
- 属于哪个项目
联犀当前把用户上下文也放进消息头里,就是为了让消费端尽可能拿到与同步链路一致的业务上下文。
这样消费逻辑在做鉴权、过滤或审计日志时,就不用再额外猜测调用来源。
设备链路为什么还需要 msgToken
平台内部可以依靠 tracing 上下文把链路串起来,但设备链路多了一层特殊性:
设备不一定理解平台内部的 trace 体系。
所以联犀当前在设备上下行场景里,还会额外使用 msgToken 作为请求-响应关联标识。
它的作用不是取代 traceID,而是补足设备侧语义:
- 云端下发一条指令时带上
msgToken - 设备上报结果时继续带上同一个
msgToken - 平台内部日志和设备调试日志可以围绕这个标识对齐
你可以把它理解成:
- traceID:平台内部服务链路的主线
msgToken:平台与设备交互的业务关联线
两者结合起来,才更接近真实的全链路。
MQTT 和消息队列为什么都要纳入同一思路
很多系统会把 MQTT 单独看成“设备协议问题”,把消息队列看成“后端异步问题”。
联犀当前更倾向于把两者统一看成“跨边界传递上下文”的问题。
无论是:
- NATS 中的事件消息
- MQTT 中的设备消息
- 其他需要跨进程、跨节点传递的数据
只要它会让业务上下文离开当前调用栈,就应该尽量补上统一的上下文透传能力。
这样做的价值是:
- tracing 模型统一
- 日志分析方式统一
- 排障习惯统一
而不是每种通道都发展出一套各自的观察方式。
为什么“能追到业务调用位置”很重要
很多追踪系统做到最后,会产生一种错觉:
trace 图很完整,所以问题就一定容易排。
但实际上,开发者最后总要落回代码。
所以链路追踪的价值,最终还是要体现在:
- 能定位到哪个业务逻辑触发了 SQL
- 能定位到哪条消息从哪里发出
- 能定位到哪段设备链路开始偏离预期
联犀当前在日志设计里比较强调这一点。
不是只关心 span 有没有打出来,而是关心开发者最后是否能借着日志快速回到真正的代码位置。
总结
联犀当前的全链路追踪,并不是某一个 tracing 组件的单点能力,而是几部分一起配合:
- API 与 RPC 入口 tracing。
- GORM 自定义 logger 补齐 SQL 层的业务定位。
- 消息总线统一封装 trace 和用户上下文。
- 设备上下行通过
msgToken建立业务关联。
这套设计解决的核心问题只有一个:
当一次请求跨过 HTTP、RPC、消息、数据库和设备交互之后,你还能不能把它重新拼回一条完整链路。
如果答案是可以,全链路追踪才真正有了工程价值。
更新日志
2026/5/18 10:48
查看所有更新日志
43ef3-docs(blog): 新增后端与架构系列技术博客 18 篇,更新原有 7 篇于33dd7-doc: 更换皮肤到最新版于d4fa0-doc: 更换皮肤到最新版于da920-doc: 完善文档于d8bee-doc: 完善文档于
