IT 论文精读 · PAPER 26

Dapper:大规模分布式系统追踪

Sigelman 等 · Google · 技术报告 2010

EN →

这篇论文干了什么?

2010 年,Google 公开了内部工具 Dapper:你在网页上敲一次搜索、点一次「购买」,背后其实有成百上千台机器接力干活。以前一旦这次请求变慢或出错,没人说得清「到底卡在哪台机器、哪个环节」。Dapper 给每一次请求发一张「全程行程单」,把它一路经过了哪些服务、每一站花了多久,全都串起来记下来。今天所有讲「可观测性」「分布式追踪」的系统——Zipkin、Jaeger、OpenTelemetry——都是照着 Dapper 的样子做的。

旧世界的痛

大公司的一次请求早就不是「一台服务器算完返回」那么简单了。你搜一个词,前端把它同时分发给几十个后端:一个查网页、一个查图片、一个查广告、一个查拼写纠正……每个后端又各自去问更下面的一串服务。这样一层层散开,一次请求能牵动上千台机器。问题来了:整件事慢了 100 毫秒,是谁拖的后腿?负责前端的工程师看不到后端内部,负责某个后端的人也不知道自己是被谁、在整条链路的哪一环调用的。每个人只掌握一小块拼图,没有一个人能看到一次请求的全貌——这在故障排查时是致命的。

那张「行程单」

Dapper 的点子是:给每一次进来的请求发一个独一无二的编号,然后让这个编号跟着请求跑遍全程——请求传到哪台机器,编号就带到哪台机器。每一站在开始和结束时都记一笔「我是几点几分接到的、几点几分干完的、我是被谁叫来的」。事后把同一个编号的所有记录收集到一起,就能拼出一棵完整的调用树:谁调了谁、每段花了多久、慢在哪一枝,一目了然。就像给一个跨越十几个部门流转的申请单,全程贴一张统一的追踪条码。

关键的巧思有两个。一是工程师几乎不用改自己的代码:Google 全公司的服务都用同一套底层通信库,Dapper 只在这套公共库里埋了记录的代码,于是所有服务「自动」就被追踪上了。二是不全记、只抽样:请求量太大,条条都记会拖慢系统、也存不下,所以 Dapper 每一千多次请求才完整记一次——对流量巨大的系统,抽这么点样本已经足够看清规律,代价却小到可以忽略。

它到底怎么帮上忙?

有了全程行程单,很多以前靠猜的事变得能直接看:一次慢请求,点开它的调用树,就知道是某个下游服务卡了、还是网络等待久了;想知道「我这个服务到底依赖了哪些别人的服务」,把海量行程单一汇总就画得出依赖地图;追查一个跨十几个团队的诡异 bug,不用再挨个团队开会对时间线,一张追踪图摆出来,责任落到哪一段清清楚楚。它把「分布式系统像个黑箱」这件事,变成了「能一层层点开看」。

说句诚实的:抽样是把双刃剑。对海量流量它很管用,但如果你要查的正是那种一万次才出一回的罕见故障,那一次很可能没被抽中、没留下记录——后来的追踪系统为此补了「先全记、发现异常再决定留哪条」的办法。

一句话记住

给每次请求发一个全程带着走的编号,在公共通信库里自动记下它经过的每一站与耗时,事后拼成一棵调用树——工程师不改代码、靠抽样几乎零开销,就能看清一次请求在成千上万台机器间到底走了哪条路、慢在哪里。这套「trace / span / 上下文传递」的模型,成了今天所有分布式追踪与可观测性系统的蓝本。

想看调用树的结构图、采集流水线和开销数字? → 切到精读版