分布式链路追踪概述:什么是分布式追踪,为什么需要它
我先问个问题:当你负责的系统从单机变成几十个微服务,用户报障说“下单很慢”,你打算怎么查?
我当年第一次面对这种场景时,第一反应是去翻每个服务的日志。嗯,结果你猜怎么着?翻了半小时,发现日志时间戳差了10秒——原来是不同服务器时钟没同步。当时我就想,要是能把一次请求的完整路径串起来,像看一条线一样,该多好。
什么是分布式追踪
说白了,分布式追踪就是给每一条用户请求分配一个全局唯一的ID(Trace ID),然后让这个ID在所有微服务之间传递。每个服务在处理请求时,把自己的工作片段(Span)记录下来,附带开始时间、结束时间、调用关系。最后把所有Span按Trace ID拼起来,就得到了完整的请求调用链。
我记得有一次排查支付超时问题,传统日志翻了半小时没头绪。我用分布式追踪工具一看,发现是A服务调B服务时,B服务又去调Redis,而Redis连接池满了。沿着Trace一目了然,前后不到5分钟。这就是分布式追踪的价值。
为什么需要它
来,我们看看没有分布式追踪时,你面临什么难题:
| 问题 | 传统做法 | 带来的痛苦 |
|---|---|---|
| 请求跨多个服务 | 逐个查日志,手动拼接 | 费时、容易漏、无法还原调用顺序 |
| 性能瓶颈定位 | 靠猜或压测 | 不精准,线上问题无法复现 |
| 错误传播分析 | 看异常栈,但不知道上游调用链 | 只能看到当前服务,看不到根因 |
| 依赖关系梳理 | 画架构图(往往过时) | 开发一改,图就废了 |
为什么需要?因为微服务架构里,一次请求可能经过5个、10个甚至更多的服务。任何一个环节出问题,都会影响整体。你想想看,没有链路追踪,就像在黑夜里找一只黑猫,还戴着墨镜。
核心概念
在动手之前,先把三个最基础的概念理清楚:
- Trace —— 代表一次完整的请求。从入口开始到最终响应结束,所有经过的服务都属于同一个Trace。
- Span —— 代表Trace中的一个工作单元。比如调用A服务的一个RPC、执行一个SQL、缓存一次查询,都可以是一个Span。
- Context —— 携带Trace ID和Span ID的上下文,在服务之间通过HTTP头部或RPC元数据传递。
工作流程(附SVG框架图)
下面这张图展示了分布式追踪的基本流程:用户请求从网关进入,依次经过服务A、B、C,每个服务上报自己的Span,最终在收集端合并成完整的Trace。
这个流程看起来简单,但实际落地时有不少细节。我个人习惯先让开发把Trace ID打印到业务日志里,这样即使没有可视化平台,也能通过grep快速定位。等积累经验后再上完整方案。
常见的追踪标准与工具
目前业界最主流的两个标准:
OpenTracing —— 提供一套统一的API,帮你定义Span、注入、提取上下文。我常用的Jaeger就是基于这个标准。
OpenTelemetry —— 是OpenTracing和OpenCensus的合并产物,现在已经成为CNCF的顶级项目。建议新项目直接上OTel。
工具方面,我列几个常用的:
- Jaeger:Uber开源的,部署轻量,适合中小团队。我个人最早入门就用的它。
- Zipkin:Twitter开源,社区成熟。如果你的运维团队对Spring Cloud很熟,Zipkin集成方便。
- SkyWalking:国产开源,对Java应用支持极好。性能监控和数据可视化做得不错。
- Grafana Tempo:Grafana家族,适合已经用Prometheus + Loki的团队,统一看板。
好了,这一章我们聊了什么是分布式追踪、为什么需要它、核心概念和工作流程。你还记不记得我开头说的那个下单慢的问题?用分布式追踪,5分钟就能定位到是Redis连接池的锅。后面几章我们会深入代码,教你如何在实际项目里接入、排查故障。先消化这些基础,后面不慌。