Dapper大规模的分布式系统追踪基建

概要

现代的网络服务通常实现了复杂的大规模的分布式系统。这个应用程序是由软件模块的集合构成的,它可能被不同的软件团队开发,可能使用不同的程序语言,并且可以跨越多个物理设施中的数千台机器。帮助理解系统行为和关于性能问题原因的工具,在这样的环境下是非常有用的。

这里我们介绍了Dapper的设计,谷歌生产的分布式系统追踪基建,并且描述我们的设计目标是如何实现低开销的,应用级别的透明,并且普遍的部署在了大规模的系统。dapper和其他的跟踪系统在观念上是类似的,尤其是Magpie和X-Trance,但是某些设计是它在我们环境中成功的关键,录入使用采样和将检测的限制相当少的公共库中。

这篇paper的主要目标是报告我们关于构建,部署和使用系统在俩年来的经历。因为这是衡量Dapper的首要标准:它对开发人员或者操作团队有用吗?Dapper最初是一个独立的追踪工具,但是演变成了一个监控平台,这使得不同的工具得以创建,一些是设计者没有预料到的。我们描述了一些dapper构建的分析工具,分享在谷歌中的统计,提出了一些使用的例子,并且讨论目前为止的校验教训。

1 介绍

我们构建dapper以提供给谷歌的开发者更多的关于复杂的分布式系统的信息。这样的系统是十分有趣的,因为小型服务器的大型集合是特别实惠的网络服务工作负载平台。在这个上下文中,理解系统的行为需要观察相关的跨越多个不同程序和机制的活动。

一个网页搜索的例子将会说明这种系统需要解决的挑战。一个前段服务可能分发web查询到上百台查询服务器,每哥都在自己部分内的索引进行搜索。这个查询可能也会发送给若干个其他的子系统,他们可能会执行广告,拼写检查或者找寻专门的结果,包括图片,视频,新闻等。所有的这些结果是有选择性的被合并到结果页;我们较这个模型通用搜索。总共上千个机器和许多不同的服务可能需要处理通用搜索。此外web查询用户对延迟非常的敏感,任何一个子系统的垃圾性能都会导致延迟。一个关注整体延迟的工程师可能知道存在的问题,但是猜不到哪个服务故障了,也不知道为什么表现不佳。首先,工程师可能不能精确的意识到哪个服务在被使用;新的服务和项目可能每周都会增加和修改,它们都可以添加用户可见的功能,并且改善其他的方面,比如性能和安全。第二,工程师不会是湄公河服务的内部专家;每一个都是由不同的团队构建和维护的。第三,服务和机制可能被不同的客户端共享,因此性能现象可能是另一个应用的行为导致的。例如,前端可以处理不同的请求类型,或者存储系统比如Bigtable可能在跨越多个应用程序共享时可能效率最高。

这个场景描述给了Dapper俩个最基本的需求:普适性(ubiquitous)的部署和持续监控。普适性是重要的因为即使系统的一小部分没有被监控,也会受到影响。此外,监控必须永远运行,因为通常情况下,不寻常的或者其他的值得注意的系统行为很难或不可能被重现。这个要求产生了三个具体的目标

  • 低开销:追踪系统只能有微不足道的性能影响在运行的系统上。 在一些高度优化的系统上,小的监控开销也容易被注意到,并且可能会迫使部署团队关闭跟踪系统。
  • 应用级别的透明:程序不需要注意到追踪系统。一个追踪基建如果以来应用开发人员积极合作才能发挥作用的系统是极度脆弱的,它通常会因为基建的bug或者遗漏被破坏,因此违反了普适性的需求。这非常对于谷歌这样快速迭代的开发环境非常重要。
  • 可靠性:在几年内,它需要处理谷歌地方服务和集群大小。

一个额外的设计目标是为了让追踪数据变得在它生成之后可用于分析:最好在一分钟之内。机关追踪分析系统对几个小时前的数据仍然很有价值,新的信息的可用性允许更快的对于生产异常做出反应。

真正的对应用级别的透明,可能是我们最具挑战性的设计目标,通过限制dapper的核心追踪基建到一个小型的普遍使用的线程,控制流和RPC库中实现的。通过使用第四章描述的采样,让系统具有扩展性和减少性能开销是容易的。生成的系统还包括了代码、可视化的跟踪的工具、库和API(应用执行接口)以分析大的痕迹的集合。尽管对于开发者定位性能异常的资源,有时单靠dapper就足够了。它不打算取代所有其他的工具。我们发现,Dapper的系统范围数据通常侧重于性能调查,因此其他工具可以在本地使用

1.1 介绍贡献

分布式系统追踪工具的设计空间已经被一些之前的文章调查过了,其中Pinpoint,Magpie和X-Trace与Dapper的关系最为密切。在有清楚评估重要的设计选择之前,这些系统往往在开发的早期阶段就在研究文献中进行了描述。由于Dapper已经大规模生产和运营多年,我们确定本文的重点放在Dapper部署交给我们的东西上是最合适的。我们的设计决策是如何发挥作用的,以及它在哪方面是有用的。Dapper作为性能分析工具开发平台的价值,它本身就是一个监控工具,是我们可以在回顾性评估中发现的少数意外结果之一。

尽管Dapper想Pinpoint与Magpie这样的系统分享了许多高层次的想法,我们的实现在这个领域包含了许多新的贡献。例如,我们发现采样对于低开销是必要的,特别是在高度的优化中,web服务它们对延迟非常敏感。也许更让人解压的是,对于跟踪数据的许多常见用途来说,数千个请求的一个示例就提供了足够的信息。

我们系统的另一个重要特征是我们能够实现的应用程序级透明度的程度。我们的工具仅限于软件堆栈中足够低的级别,即便是谷歌网络搜索这样的大型分布式系统,也可以在没有额外注解的情况下进行跟踪。虽然这更容易实现,因为我们部署环境具有一定程度的同质性。我们这样的做的结果表明了实现这种透明度的一些充分条件。

2 dapper中的分布式追踪

分布式服务的跟踪基础架构需要记录代表给定发起者在系统中完成的所有工作的信息。例如,图1展示了五个服务:前端(A)俩个中间层(B和C)以及俩个后端)(D和E)当一个请求(在本例中为启动器)到达了前端,它发送俩个RPC请求到服务B和C。B可以立即进行回复,但是C需要后端的D和E的工作才能恢复A,而A又反过来响应原始请求。 对于这个请求一个简单好用的分布式跟踪是消息标识符和发送每个信息时间戳事件的集合。

已经提出了俩类解决方案来汇总这些信息,以便所有的记录条目与给定的发起者关联起来(图中的RequestX),黑河和基于注释的监控方案。黑盒模式假设除了上面描述的消息记录之外没有其他的信息,并且使用统计回归技术来推断这种关联。基于注解的模式依赖于应用或者中间件显示的用全局标识符表示每条记录,该标识符将这些消息记录链接回原始请求。其中黑盒模式相较于基于注释的方法更具可移植性,由于它们依赖于统计推断,它需要更多的数据来获得足够的准确性。基于注释方法的主要缺点是需要对程序进行额外的标签。在我们的环境中,由于所有的模型使用了相同的线程模型,控制流和RPC系统,我们发现可以将工具限制在一小部分公共库中,并且实现了监控系统,它对于开发人员来说是有效透明的。

我们倾向于将Dapper的跟踪视为一个嵌套的树。然而,我们的核心数据模型并不局限于我们特定的RPC框架;我们还追踪Gmial中的SMTP等活动,来自外部世界的HTTP请求,以及对SQL服务器的出站查询。形式上,我们使用树spans和注解对dapper轨迹进行建模。

2.1 追踪树和span

在dapper的追踪树中,树节点是一个工作的基本单元我们称之为跨度(span)。但是,与它在更大的跟踪树中的位置无关,span也是一个简单的时间戳记录日志,它编码了span的开始和结束时间、任何RPC计时数据以及0个或多个特定于应用程序的注释,如第2.3节所讨论的。

我们描述了跨度是如何形成更大的跟踪结构的。dapper记录了人类可读的空间名,还有一个跨度id和父id以重建单个分布轨迹中各个跨度之间的因果关系。没有父id创建的跨称为根跨度。与特定跟踪关联的所有跨越也共享一个公共跟踪id(图中未显示)。所有的这些ID都可能是64位的唯一整数。在典型的Dapper跟踪中,我们期望对于每个RPC找到一个单个的跨度,并且基础设施的每一层都为跟踪树增加了一个额外的深度级别。

图3提供了典型的dapper跟踪范围中记录的事件的更加详细的视图。图2中这个特定的跨度描述了Helper.Call RPC。跨度的开始和结束时间以及任何RPC计时信息都由Dapper的RPC库工具记录。如果应用程序所有者选择使用自己的注释来自扩展跟踪(如图中的FOO注解)这些数据页和其余的跨度数据一起记录。

重要的是要注意,一个跨度的信息可以包含来自多个主机的信息;事实上,每个RPC跨度包含的注释来自客户端和服务端进程,双主机跨度是最常见的跨度。因此,客户端和服务单的时间戳可能来自不同机器,我们必须注意时钟偏差。在我们的分析工具中,我们利用在服务接收到请求之前,RPC客户端总是发送请求这一事实,对于响应来说页同样适用。这样,我们就有了RPC服务器端的跨度时间戳的下线和上限。

2.2 监测点

dapper能够几乎在零干预应用开发的情况下遵循分布式控制路径,通过完全依赖于通用库的监测。

  • 当线程处理跟踪的控制路径时,dapper将跟踪上下文附加到线程本地存储。追踪上下文是一个小的易于复制的跨度属性容器,如space和span id。
  • 当计算被延期或者变为异步,大多数谷歌开发人员使用公共控制流库来构造回调,并将它们调度到线程池或其他执行器中。Dapper确保此类毁掉存储它创建者的跟踪上下文,当调用回调时,此跟踪上下文与相应的线程关联。Dapper id被用来重建追踪能够透明的遵循异步控制路径。
  • 谷歌的几乎所有进程间通信都是围绕一个RPC框架构建的,该框架带有c++和Java的绑定。我们使用该框架来定义所有RPC维度。用于跟踪的RPC跨度和跟踪id从客户机传输到服务器。对于基于RPC的系统,就像在谷歌上广泛被使用的那些,这是一个重要的监测点。我们打算在非RPC通信框架发展并获得用户基础的过程中,逐步为其添加监控功能。

Dapper追踪数据是语言无关的并且,生产中的许多跟踪将使用c++和Java编写的进程中的数据结合在一起。在章节3.2中文名描述了我们在实践中做到的应用透明度级别。

2.3 注解

// C++:
const string& request = ...;
if (HitCache())
    TRACEPRINTF("cache hit for %s", request.c_str());
else
    TRACEPRINTF("cache miss for %s", request.c_str());
// Java:
Tracer t = Tracer.getCurrentTracer();
String request = ...;
if (hitCache())
    t.record("cache hit for " + request);
else
    t.record("cache miss for " + request);

图4:Dapper的注释api在c++和Java中的常用用法模式。


上面描述的检查点足以掏出复杂分布式系统的详细追踪,使核心的Dapper功能可用于未经修改的谷歌应用程序。然而,Dapper也允许应用开发者填充dapper的追踪的附加信息,这也许对监控高层及的系统行为有用或者帮助debug问题。我们允许用户通过API定义时间戳的注解,核心如4所示。这些注解可以有任意内容。为了保护Dapper用户免受意外的过度日志记录,单个追踪跨度在其总注解量上有可配置的上限。无论应用程序的行为如何,应用级别的注解不能取代结构跨度或者RPC信息。

除了简单的文本注释,Dapper也提供了键值对注解它给了操作员更多的追踪能力,比如维护计数器,记录二进制日志,以及在进程内跟随请求传输任意用户定义的数据。这个键值对注解被用来定义分布式跟踪上下文中特定应用的等价类。

2.4 采样

低开销是设计Dapper的关键,因为服务运营商不愿意部署一种尚未证明有价值的新工具,如果它对性能有任何重大的影响。此外我们希望开发人员使用注解api而不必担心额外的开销。我们还发现,某些应用的确对检测开销很敏感。因此除了让Dapper集合的监测开销尽可能小以外,我们通过只记录所有轨迹的一小部分来进一步扩展开销。我们在章节4.4中进一步探讨这种采样方案。

2.5 追踪收集

Dapper追踪记录和收集管道是一个三阶段的过程(见图5)

首先跨度数据被写入(1) 本地的日志文件,然后通过dapper的守护进程从(2)生产主机上拉取,并最终将(3)写入几个区域性Dapper Bigtable存储库中的一个单元。追踪号被布置为单个Bigtable行,每一列对应一个跨度。因为单个追踪有任意个数量的跨度,Bigtable对于稀疏表的支持在这里很有用。跟踪数据的中位数延迟-跟踪数据收集的中位延迟(即数据从检测的应用程序二进制文件传播到中央存储库所花费的时间)小于15秒。98百分位的延迟本身随时间呈现出双峰分布。月百分之75的情况下,98百分位的收集延迟小于2分钟,但是另外大约25%的事件会增加到可能好几个小时。

Dapper还提供了一个API来简化对存储库中跟踪数据的访问。谷歌的开发人员使用API来构建通用和特定于应用程序的分析工具,章节5包含了用法的更多信息。

2.5.1 带外追踪数据收集

如上所述,Dapper系统使用请求树本身执行跟踪日志记录和带外收集。这么做是为了俩个可以理解的原因。首先是带内采集方案-其中追踪数据被发送回RPC响应头-会影响应用的网络动态。在大的谷歌系统中,发现具有数千个跨度的追踪并不罕见。然而,RPC请求-任然可以相对较小:通常小于10kb。在这样的情况下,带内的dapper根据数据将使应用程序数据相形见绌,并且使随后的分析结果产生偏差。其次带内收集方案假设所有rpc请求都是完美嵌套的。我们发现许多中间件系统在后端返回结果之前,向调用者返回结果的系统。带内收集系统无法解释这种非嵌套的分布式执行模式。

2.6 安全和隐私考虑

因为分析工具可能会发现负载数据中的模式,记录RPC负载信息的量会丰富dapper的痕迹,这可以解释性能异常。然而在某些情况下负载数据可能包含信息,这些信息不应该透露给未经授权的内部用户,包括从事性能调试的工程师。

因此安全和隐私相关的担忧是不可协商的,Dapper存储RPC方法的名称,但此时不记录任何有效负载数据。相反应用级别的注解提供了一个方便的选择机制:应用开发人员可以关联其认为有用的任何数据以方便之后的跨度分析。

dapper也提供了没有被设计者期待的一些安全好处。公共安全协议的参数,Dapper用于通过适当级别的身份验证或加密来监视应用程序是否满足安全策略。Dapper还可以提供信息,以确保按预期执行基于策略的系统隔离,即,承载敏感数据的应用程序不与未经授权的系统组件交互。这些测量方法提供了比源代码审计更大的保证。

3 Dapper部署状态

dapper已经在我们生产环境的链路追踪系统俩年了。在这一章节,我们报告系统的状态,关注它如何很好的满足了我们普适部署的目标和应用级别的透明

3.1 Dapper运行库

基本上大部分Dapper代码的关键部分基于基础RPC的基础设施,线程和控制流库,它包含了跨度创建、采样和记录到本地磁盘。除了轻量级,这些代码需要稳定和健壮,由于它与大量的应用程序相关联,使得维护和Bug修复变得困难。核心的监控代码不到1000行C++代码,不到800行java代码。key-value注解的实现添加了500行代码。

3.2 生产覆盖

Dapper的穿透力可以从俩个方向进行评估:能够生成Dapper追踪信息的生产进程的比例(及那些链接了Dapper监控运行时的库)以及运行Dapper跟踪手机守护进程的生产机器的比例。Dapper的守护进程基本机器映像的一部分,让它出现在谷歌几乎所有的服务器上。要确定Dapper可以运行的进程的准确分数是困难的,因为不生成跟踪信息的进程对Dapper是不可见的。然而,考虑到dapper工具库的的普适性,几乎每个谷歌生产环境都支持跟踪。

在某些情况下,Dapper无法正确的遵循控制路径。这些通常源于使用非标注的控制流原语,或者Dapper错误的将因果归因于不相关的事件。Dapper提供了一个简单的库莱帮助开发者手动的控制追踪传播作为方案。目前有40个C++源于和33个Java应用他们需要一些手动追踪传播,是数以千计应用中的一小部分。这也是非常少的没有使用非工具通信库程序数量。(比如原始的TCP或者 SOAP RPC)因此不支持Dapper的追踪。如果认为重要,可以将Dapper支持添加到这些应用程序中。

Dapper追踪可以反过来作为生产安全度量。事实上这在早期是关闭的,直到我们对它的稳定性和低开销建立了信心。Dapper团队偶尔执行审计,查找配置的更改其中追踪由服务所有者关闭。这样的更改很少见,通常是源于对于监控开销的担忧。经过进一步的调查,所有的这些变化都已经恢复,实际开销的测量这是无关紧要的。

3.3 使用追踪注解

程序员倾向于使用特定应用注解作为分布式调试日志文件或者通过特定应用的特性将痕迹进行分类。例如所有的Bigtable请求是使用正在访问表的名称被注解的。当前70%的Dapper跨度和90%的Dapper痕迹至少有一个程序指定的注释。

41个java和68个C++应用已经添加了自定义应用注解以更好的理解服务中跨度内的活动。值得注意的是,我们的java开发者适配了的注解API比C++同行更多的注解。这可能是因为Java的工作负载倾向于接近用户端;这类应用程序通常处理更广泛的请求组合,因此相对复杂的控制路径。

4 管理追踪开销

跟踪系统的代价是被监视系统的性能下降,这是由于追踪产生的收集开销和存储和分析追踪数据所需要的资源量。尽管有人会说,一个有价值的追踪基建值得牺牲性能,我们相信,如果极限的开销可以忽略,那么将大大的促进初步的采用。

在这一章节我们提出了Dapper工具操作的主要开销,跟踪收集的开销,和Dapper在生产工作负载上带来的影响。我们也描述了Dapper如何适应追踪采样机制来帮助我们平衡降低开销的需求对代表性痕迹的渴望。

4.1 跟踪产生的开销

追踪产生的开销是Dapepr性能占用的关键部分,因为收集和分析在紧急情况下更容易关闭。在Dapper运行库中追踪生成开销的最重要的资源是创建和销毁跨度和注释,并且记录他们到本地磁盘以进行随后的收集。根跨度创建和销毁平均要204纳秒,对于非跟跨度的相同操作需要176纳秒。不同之处在于为根跨度分配一个全局唯一的tranceId所增加的成本。

如果没有对跨度采样进行跟踪,额外的跨度注解几乎可以忽略不计,由Dapper运行时的本地线程所组成,平均9纳秒。如果对其进行采样,注解追踪字符串字面量-类似于图4-平均化肥40纳秒。这些测量是在2.2GHZ 的x96服务器上进行的。

写入本地磁盘几乎是Dapper运行时库中最昂贵的操作,但是它们可见的开销大大的减少了,因为每个磁盘合并了多个日志文件页写操作,并且相对于跟踪的应用程序一步执行。然而,日志写入操作可能对于高吞吐量的应用程序产生明显的影响,尤其是所有的请求都被跟踪了。我们在web查询工作负载中测量这个开销在4.3章。

4.2 跟踪收集开销

读取本地的数据页会干扰正在监视的前台工作负载。表1展示了在不切实际的负载测试下,Dapper守护进程中CPU利用率最坏的例子。守护进程不会使用超过0.3%的生产机器核心,并且只有很小的内存占用(在堆碎片的噪声中)。在沉重负载主机机制中cpu出现争用,我们还将Dapper的守护进程设置为尽可能低的优先级,

Dapper也是网络资源的轻消耗者,在我们的存储库中,每个span支队应用于426个字节平均。作为应用网络活动中的一部分,我们监控,Dapper数据收集对应的流量小于0.01%的在谷歌生成环境中的网络流量。

4.3 生产环境工作负载的影响

高吞吐量的在线服务,对于每个请求使用大量机器最需要有效的跟踪的;这导致了生成了大量的追踪数据,同事他们也对性能干扰最为敏感。在表2中我们使用了我们的Web查询集群作为例子;当我们改变采样痕迹的比利时,我们衡量Dapper的平均延迟的和吞吐量的影响。

我们看到,虽然对吞吐量的影响不是很显著,但为了避免明显的延迟下降,追踪采样确实是必要的。然而,采样频率小于1/16相关的延迟和吞吐量都在实验的误差范围内。在实践中,我们发现当使用低至1/1024的采样率时,仍然有足够数量的跟踪数据用于大容量服务。保持极限Dapper开销最低是非常重要的,因为它为应用程序使用注释API的全部宽度提供了一些余地而不用担心性能损失。使用较低的采样频率还有一个额外的好处,即允许数据在被垃圾收集之前在主机的本地磁盘上保存更长时间,这为收集基础设施提供了更大的灵活性。

4.4 自适应采样

归属于任何给定进程的Dapper开销与单位时间内进行采样的跟踪数量成正比。Dapper的第一个生产版本使用了对谷歌所有的过程使用统一的采样率。每1024次对候选者进行一次采样。这个简单的方案对于我们高吞吐量的在线系统很有效,因为绝大多数感兴趣的的事件仍然可能出现足以被捕获。

然而更低的流量负载可能遗漏掉重要的事件,在如此低采样率下,同事容忍更高的采样率和可接受的性能开销。对于这样系统的解决方案是重写默认的采样率,这需要我们在Dapper在Dapper中需求减少干预。我们正在部署一种自适应的采样方案,它不是由均匀抽样概率参数化的,而是按照单位时间采样痕迹的期望速率。这样,低流量的工作负载会自动提高采样率,而高流量会降低采样率,因此开销依然可以被控制。所使用的事迹采样率联通轨迹本身一起被记录下来。这有助于在围绕Dapper数据构建的分析工具中准确计算跟踪频率。

4.5 应对侵略性采样

Dapper的新用户经常想知道,降低采样的概率,对于高流量服务通常低至0.01%-会干扰它们的分析。我们在谷歌的校验让我们相信,对于高吞吐量的服务,积极的采样并不妨碍重要的分析,如果在这样的系统中出现了一个值得注意的执行模式,它会发生上千次。业务量较低的业务,可能是每秒十几个请求,而不是每秒数万个请求-有能力追踪每一个请求;这就是促使我们决定转向自适应采样率的原因。

4.6 收集期间的额外采样

上面的采样机制被设计成在应用程序中最小化可感知开销,它包含了Dapper的运行时库。Dapper团队也需要控制写入中央存储库的数据总量的大小,因此我们为了这个目的加入了第二轮采样。

目前我们的生产集群产生超过1TB的追踪数据采样每天。在数据从生产环境被记录后,Dapper用户希望数据在至少天内保持可用。采样大量请求还会使Dapper收集器接近Dapper Bigtable仓库的写入吞吐量极限,导致其不堪重负。为了保持灵活的资源需求和累计Bigtable写吞吐量的灵活性,我们在系统本身增加了对额外采样的支持。我们利用给定追踪所有跨度的事实-虽然它们可能分布在数千个不同的机器上-共享相同的追踪id。对于每个收集胸痛看到的每个跨度,我们将相关联的跟踪Id哈希为标量z,其中0≤z≤1。如果z小于集合抽样系数 ,我们保持跨度写入它到Bigtable。不然我们扔掉它。通过依赖采样决策的跟踪id,我们采样或者丢弃整个痕迹,而不是痕迹中的某个跨度。我们发现这个额外的配置参数让收集管道的管理员变得简单,因为我们可以通过更改配置文件中的单个参数轻松调整全局写速率。

如果对于追踪和收集系统同时使用一个采样参数会变得更简单,但是在所有已经部署的二进制文件中快速的挑战是运行采样配置是不可行的。我们已经选择了一个运行时采样率,它产生的数据略多于我们写入存储库的数据,我们通过二次采样系数来控制写入速率。Dapper管道维护更容易,因为我们可以通过对二次采样配置进行一次更改来立即增加或减少我们的全球覆盖范围和写入速率。

5 通用的Dapper工具

6 经历

7 其他的校验教训

到目前为止,我们对dapper的体验大体达到了我们的预期,有一些我们完全没有撂倒的积极方面。我们对未预料到的用例十分满意。除了第6章中描述的几个经验外,这些还包括了资源哦天哪攻击系哦他那个,检查敏感服务是否符合特定行为的工具,和RPC策略分析,等等。我们将这些意想不到的使用部分归因于想开发人员开放数据跟踪存储的决定,通过一个简单的编程接口,因为这使我们能够利用更强大的社区创造力。此外为遗留的工作添加dapper负载也比预期想的简单,只需要重新编译现有库的程序版本,它们使用了受支持的线程、控制流、RPC框架。

Dapper在谷歌的广泛使用也提供了一些关于它局限性的反馈样例。下面将介绍一些我们发现的迄今为止最重要的问题。

合并的影响:我们的模型隐含假设各种子系统将会将一次为一个跟踪请求做工作。在某些情况下,在一次对一组请求执行操作之前缓冲几个请求会更加有效(磁盘的写合并就是这个例子)。在这样的情况下,追踪请求会导致大量的工作。此外如果多个追踪请求被批处理在一起,它们中只有一个看起来对跨度负责,由于我们依赖于每个跟踪的唯一trace id。我们正在考虑能够识别这些情况并记录消除歧义所需的最小信息量的解决方案。

追踪批处理工作负载: Dapper的设计目标是在线的服务于系统,最初的目标是理解用户请求谷歌所导致的行为。然而,离线数据密集工作负载,比如那些适合MapReduce的,也可以在这个性能洞察中收益。在这个例子中我们需要关联tance id和其他有意义的工作单元,例如输入数据中的一个键,或者MapReduce分片。

找到根问题:Dapper可以有效的确定系统的哪个部分正在经理减速,但它并不总能找到根源问题。比如一个请求很慢不是由于它自己的问题,是由于其他的请求在它之前排队。程序可以使用应用级别的行为去传播队列的大小或者跟踪系统的过载情况。此外,如果这种效果是常见的,那么ProfileMe中提出的配对采样技术可能会被证明是有用的。它包括采样俩个时间重叠的请求,观察它在整个系统中的相对延迟。

记录内核级别的信息:在内核级别可见的详细信息在一些时候可能会帮助根问题确定。我们有许多工具能够跟踪或分析内核的执行,但是把这些信息和上下文连起来,这在用户层面很难以不引人注意的方式完成。我们在研究一种这种方案,其中我们从用户级别获取一些内核活动参数的快照,并且将他们和活动跨度关联起来。

9结论

在这篇论文中我们介绍了Dapper,谷歌的生产环境分布式系统追踪平台,并且介绍了我们开发和使用它的经理。Dapper被部署在几乎所有谷歌的系统上,并且允许我们绝大部分的我们最大的工作负载能被跟踪,而不需要任何应用级别的修改,并且没有明显的性能影响。Dapper对开发人员和运营团队的实用性通过主要跟踪用户级别的普及程度已经被证明,这里通过用例的例子来说明,甚至有些是没有被设计者预料到的。

在我们的认知中,这是第一个上报了大的,生产分布式系统追踪框架的文章。事实上我们主要的贡献来自于我们对于系统过去俩年操作的回顾。比如,我们分析,将最小的应用透明追踪功能和简单的API相结合以便程序员增强跟踪是值得的。

我们相信Dapper达到了高度的应用级别透明超过了过去任何基于注解的分布式追踪系统,正数少量的需要人工干预的工作负载所示。虽然我们的计算不是的不寻常的同质性促进了这一点,这还是非常有挑战性。最重要的是,我们的设计提出了对于应用级别透明的条件,我们希望这可以帮助其他人开发更多异构环境的解决方案。

最后,通过向内部开发人员开放Dapper的存储库,我们已经允许创建许多分析库,比Dapper团队完成的成功还要多,极大的利用了设计和实现工作。

Last modification:December 27, 2024
如果觉得我的文章对你有用,请随意赞赏