目录
择要
1.介绍
2. Dapper的分布式跟踪
2.1 跟踪树和span
2.2 植入点
2.3 Annotation
2.4 采样率
2.5 跟踪的收集
2.5.1 带外数据跟踪收集
2.6 安全和隐私考虑
3. Dapper部署状况
3.1 Dapper运行库
3.2 生产环境下的涵盖面
3.3 跟踪Annotation的利用
4. 处理跟踪消耗
4.1 生成跟踪的消耗
4.2 跟踪收集的斲丧
4.3 在生产环境下对负载的影响
4.4 可变采样
4.5 应对积极采样(Coping with aggressive sampling)
4.6 在收集过程中额外的采样
5. 通用的Dapper工具
5.1 Dapper Depot API
5.1.1 DAPI在Google内部的利用
5.2 Dapper的用户接口
6. 履历
6.1 在开发中利用Dapper
6.1.1 与异常监控的集成
6.2 办理延迟的长尾效应
6.3 推断服务依靠
6.4 差异服务的网络利用率
6.5 分层和共享存储系统
6.6 Dapper的救火能力(Firefighting)
7. 其他收获
8. 相关产品
9. 总结
干货分享,感谢您的阅读!
论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》介绍了谷歌开发的大规模分布式系统跟踪基础办法Dapper。Dapper旨在通过提供跨多个服务和计算机的详细跟踪信息,资助开发人员理解和调试复杂的分布式系统。论文讨论了Dapper背后的动机、其架构以及在诊断性能题目和优化分布式系统方面所提供的实际长处。本文作为回首经典,重新学习,翻译的同时加入一些现有的理解。
择要
今世互联网服务通常是作为复杂的、大规模的分布式系统实现的。这些应用程序由软件模块集合构建而成,这些模块可能由差异的团队开发,可能利用差异的编程语言,而且可能跨越多个物理办法上的许多千台计算机。在如许的环境中,资助理解系统行为并对性能题目举行推理的工具优劣常宝贵的。 在这里,我们介绍了Dapper的计划,这是谷歌的生产分布式系统跟踪基础办法,并描述了我们是如何实现低开销、应用级透明度和在非常大规模系统上的普遍部署这些计划目标的。Dapper与其他跟踪系统,特别是Magpie和X-Trace,分享概念上的相似之处,但在某些计划选择上,特别是利用采样和将仪器化限制在一小部分常见库上,这些选择对其在我们的环境中取得成功至关告急。 本文的重要目标是陈诉我们在两年多时间内构建、部署和利用该系统的履历,由于Dapper的重要成功度量是它对开发和运维团队的有用性。Dapper最初是一个独立的跟踪工具,但已发展成为一个监控平台,使得可以创建许多差异的工具,此中一些并不是其计划者所预期的。我们描述了利用Dapper构建的一些分析工具,分享了在谷歌内部的利用统计,提供了一些示例用例,并讨论了迄今为止所学到的履历教导。
1.介绍
我们开发Dapper是为了收集更多的复杂分布式系统的行为信息,然后呈现给Google的开发者们。如许的分布式系统有一个特别的长处,由于那些大规模的低端服务器,作为互联网服务的载体,是一个特别的经济划算的平台。想要在这个上下文中理解分布式系统的行为,就必要监控那些横跨了差异的应用、差异的服务器之间的关联动作。
下面举一个跟搜索相关的例子,这个例子论述了Dapper可以应对哪些挑战。比如一个前段服务可能对上百台查询服务器发起了一个Web查询,每一个查询都有自己的Index。这个查询可能会被发送到多个的子系统,这些子系统分别用来处理广告、举行拼写检查或是查找一些像图片、视频或消息如许的特别结果。根据每个子系统的查询结果举行筛选,得到最闭幕果,最后汇总到页面上。我们把这种搜索模型称为“全局搜索”(universal search)。总的来说,这一次全局搜索有可能调用上千台服务器,涉及各种服务。而且,用户对搜索的耗时是很敏感的,而任何一个子系统的低效都导致导致终极的搜索耗时。如果一个工程师只能知道这个查询耗时不正常,但是他无从知晓这个题目到底是由哪个服务调用造成的,或者为什么这个调用性能差强人意。起首,这个工程师可能无法正确的定位到这次全局搜索是调用了哪些服务,由于新的服务、乃至服务上的某个片段,都有可能在任何时间上过线或修改过,有可能是面向用户功能,也有可能是一些比方针对性能或安全认证方面的功能改进。其次,你不能苛求这个工程师对所有到场这次全局搜索的服务都了如指掌,每一个服务都有可能是由差异的团队开发或维护的。再次,这些袒露出来的服务或服务器有可能同时还被其他客户端利用着,以是这次全局搜索的性能题目甚至有可能是由其他应用造成的。举个例子,一个背景服务可能要应付各种各样的请求类型,而一个利用服从很高的存储系统,比如Bigtable,有可能正被反复读写着,由于上面跑着各种各样的应用。
上面这个案例中我们可以看到,对Dapper我们只有两点要求:无所不在的部署,持续的监控。无所不在的告急性不言而喻,由于在利用跟踪系统的举行监控时,即便只有一小部分没被监控到,那么人们对这个系统是不是值得信托都会产生巨大的质疑。另外,监控应该是7x24小时的,毕竟,系统异常或是那些告急的系统行为有可能出现过一次,就很难甚至不太可能重现。那么,根据这两个明确的需求,我们可以直接推出三个具体的计划目标:
- 低斲丧:跟踪系统对在线服务的影响应该做到足够小。在一些高度优化过的服务,纵然一点点消耗也会很轻易察觉到,而且有可能迫使在线服务的部署团队不得不将跟踪系统关停。
- 应用级的透明:对于应用的程序员来说,是不必要知道有跟踪系统这回事的。如果一个跟踪系统想见效,就必须必要依靠应用的开发者主动共同,那么这个跟踪系统也太脆弱了,往往由于跟踪系统在应用中植入代码的bug或疏忽导致应用出题目,如许才是无法满足对跟踪系统“无所不在的部署”这个需求。面临当下想Google如许的快节奏的开发环境来说,尤其告急。
- 延展性:Google至少在将来几年的服务和集群的规模,监控系统都应该能完全把控住。
一个额外的计划目标是为跟踪数据产生之后,举行分析的速度要快,抱负情况是数据存入跟踪堆栈后一分钟内就能统计出来。尽管跟踪系统对一小时前的旧数据举行统计也是相称有价值的,但如果跟踪系统能提供足够快的信息反馈,就可以对生产环境下的异常状况做出快速反应。
做到真正的应用级别的透明,这应该是当下面临的最挑战性的计划目标,我们把核心跟踪代码做的很轻便,然后把它植入到那些无所不在的公共组件种,比如线程调用、控制流以及RPC库。利用自适应的采样率可以使跟踪系统变得可伸缩,并降低性能消耗,这些内容将在第4.4节中提及。结果展示的相关系统也必要包含一些用来收集跟踪数据的代码,用来图形化的工具,以及用来分析大规模跟踪数据的库和API。虽然单独利用Dapper有时就足够让开发人员查明异常的来源,但是Dapper的初志不是要取代所有其他监控的工具。我们发现,Dapper的数据往往侧重性能方面的观察,以是其他监控工具也有他们各自的用处。
2. Dapper的分布式跟踪
分布式服务的跟踪系统必要记载在一次特定的请求后系统中完成的所有工作的信息。举个例子,图1显现的是一个和5台服务器相关的一个服务,包括:前端(A),两个中心层(B和C),以及两个后端(D和E)。当一个用户(这个用例的发起人)发起一个请求时,起首到达前端,然后发送两个RPC到服务器B和C。B会马上做出反应,但是C必要和后端的D和E交互之后再返还给A,由A来响应最初的请求。对于如许一个请求,简单实用的分布式跟踪的实现,就是为服务器上每一次你发送和吸收动作来收集跟踪标识符(message identifiers)和时间戳(timestamped events)。
为了将所有记载条目与一个给定的发起者(比方,图1中的RequestX)关联上并记载所有信息,如今有两种办理方案,黑盒(black-box)和基于标注(annotation-based)的监控方案。黑盒方案[1,15,2]假定必要跟踪的除了上述信息之外没有额外的信息,如许利用统计回归技能来推断两者之间的关系。基于标注的方案[3,12,9,16]依靠于应用程序或中心件明确地标记一个全局ID,从而毗连每一条记载和发起者的请求。虽然黑盒方案比标注方案更轻便,他们必要更多的数据,以得到足够的精度,由于他们依靠于统计推论。基于标注的方案最重要的缺点是,很显着,必要代码植入。在我们的生产环境中,由于所有的应用程序都利用相同的线程模型,控制流和RPC系统,我们发现,可以把代码植入限制在一个很小的通用组件库中,从而实现了监测系统的应用对开发人员是有效地透明。
我们倾向于认为,Dapper的跟踪架构像是内嵌在RPC调用的树形布局。然而,我们的核心数据模型不只范围于我们的特定的RPC框架,我们还能跟踪其他行为,比方Gmail的SMTP会话,外界的HTTP请求,和外部对SQL服务器的查询等。从形式上看,我们的Dapper跟踪模型利用的树形布局,Span以及Annotation。
2.1 跟踪树和span
在Dapper跟踪树布局中,树节点是整个架构的根本单位,而每一个节点又是对span的引用。节点之间的连线体现的span和它的父span直接的关系。虽然span在日记文件中只是简单的代表span的开始和结束时间,他们在整个树形布局中却是相对独立的,任何RPC相关的时间数据、零个或多个特定应用程序的Annotation的相关内容会在2.3节中讨论。
在图2中阐明了span在一个大的跟踪过程中是什么样的。Dapper记载了span名称,以及每个span的ID和父ID,以重建在一次追踪过程中差异span之间的关系。如果一个span没有父ID被称为root span。所有span都挂在一个特定的跟踪上,也共用一个跟踪id(在图中未示出)。所有这些ID用全局唯一的64位整数标示。在一个典型的Dapper跟踪中,我们希望为每一个RPC对应到一个单一的span上,而且每一个额外的组件层都对应一个跟踪树型布局的层级。
图3给出了一个更详细的典型的Dapper跟踪span的记载点的视图。在图2中这种某个span表述了两个“Helper.Call”的RPC(分别为server端和client端)。span的开始时间和结束时间,以及任何RPC的时间信息都通过Dapper在RPC组件库的植入记载下来。如果应用程序开发者选择在跟踪中增加他们自己的注释(如图中“foo”的注释)(业务数据),这些信息也会和其他span信息一样记载下来。
记住,任何一个span可以包含来自差异的主机信息,这些也要记载下来。究竟上,每一个RPC span可以包含客户端和服务器两个过程的注释,使得链接两个主机的span会成为模型中所说的span。由于客户端和服务器上的时间戳来自差异的主机,我们必须考虑到时间偏差。在我们的分析工具,我们利用了这个究竟:RPC客户端发送一个请求之后,服务器端才能吸收到,对于响应也是一样的(服务器先响应,然后客户端才能吸收到这个响应)。如许一来,服务器端的RPC就有一个时间戳的一个上限和下限。
2.2 植入点
Dapper可以以对应用开发者近乎零浸入的成本对分布式控制路径举行跟踪,险些完全依靠于基于少量通用组件库的改造。如下:
- 当一个线程在处理跟踪控制路径的过程中,Dapper把这次跟踪的上下文的在ThreadLocal中举行存储。追踪上下文是一个小而且轻易复制的容器,此中承载了Scan的属性比如跟踪ID和span ID。
- 当计算过程是延迟调用的或是异步的,大多数Google开发者通过线程池或其他执行器,利用一个通用的控制流库来回调。Dapper确保所有如许的回调可以存储这次跟踪的上下文,而当回调函数被触发时,这次跟踪的上下文会与得当的线程关联上。在这种方式下,Dapper可以利用trace ID和span ID来辅助构建异步调用的路径。
- 险些所有的Google的进程间通信是建立在一个用C++和Java开发的RPC框架上。我们把跟踪植入该框架来定义RPC中所有的span。span的ID和跟踪的ID会从客户端发送到服务端。像那样的基于RPC的系统被广泛利用在Google中,这是一个告急的植入点。当那些非RPC通信框架发展成熟并找到了自己的用户群之后,我们会计划对RPC通信框架举行植入。
Dapper的跟踪数据是独立于语言的,很多在生产环境中的跟踪联合了用C++和Java写的进程的数据。在3.2节中,我们讨论应用程序的透明度时我们会把这些理论的是如何实践的举行讨论。
2.3 Annotation
上述植入点足够推导出复杂的分布式系统的跟踪细节,使得Dapper的核心功能在不改动Google应用的情况下可用。然而,Dapper还答应应用程序开发人员在Dapper跟踪的过程中添加额外的信息,以监控更高级别的系统行为,或资助调试题目。我们答应用户通过一个简单的API定义带时间戳的Annotation,核心的示例代码入图4所示。这些Annotation可以添加任意内容。为了保护Dapper的用户意外的过分热衷于日记的记载,每一个跟踪span有一个可设置的总Annotation量的上限。但是,应用程序级的Annotation是不能更换用于体现span布局的信息和记载着RPC相关的信息。
除了简单的文本Annotation,Dapper也支持的key-value映射的 Annotation,提供给开发人员更强的跟踪能力,如持续的计数器,二进制消息记载和在一个进程上跑着的任意的用户数据。键值对的Annotation方式用来在分布式追踪的上下文中定义某个特定应用程序的相关类型。
2.4 采样率
低消耗的是Dapper的一个关键的计划目标,由于如果这个工具价值未被证实但又对性能有影响的话,你可以理解服务运营人员为什么不乐意部署它。何况,我们想让开发人员利用Annotation的API,而不消担心额外的开销。我们还发现,某些类型的Web服务对植入带来的性能消耗确实非常敏感。因此,除了把Dapper的收集工作对根本组件的性能消耗限制的尽可能小之外,我们另有进一步控制消耗的办法,那就是碰到大量请求时只记载此中的一小部分。我们将在4.4节中讨论跟踪的采样率方案的更多细节。
2.5 跟踪的收集
Dapper的跟踪记载和收集管道的过程分为三个阶段(参见图5)。起首,span数据写入(1)当地日记文件中。然后Dapper的守护进程和收集组件把这些数据从生产环境的主机中拉出来(2),终极写到(3)Dapper的Bigtable堆栈中。一次跟踪被计划成Bigtable中的一行,每一列相称于一个span。Bigtable的支持稀疏表格布局正适合这种情况,由于每一次跟踪可以有任意多个span。跟踪数据收集(即从应用中的二进制数据传输到中心堆栈所花费的时间)的延迟中位数少于15秒。第98百分位的延迟(The 98th percentile latency)往往随着时间的推移呈现双峰型;大约75%的时间,第98百分位的延迟时间小于2分钟,但是另外大约25%的时间,它可以增涨到几个小时。
Dapper还提供了一个API来简化访问我们堆栈中的跟踪数据。 Google的开发人员用这个API,以构建通用和特定应用程序的分析工具。第5.1节包含更多如何利用它的信息。
2.5.1 带外数据跟踪收集
tip1:带外数据:传输层协议利用带外数据(out-of-band,OOB)来发送一些告急的数据,如果通信一方有告急的数据必要关照对方时,协议能够将这些数据快速地发送到对方。为了发送这些数据,协议一样平常不利用与平凡数据相同的通道,而是利用另外的通道。
tip2:这里指的in-band策略是把跟踪数据随着调用链举行传送,out-of-band是通过其他的链路举行跟踪数据的收集,Dapper的写日记然后举行日记采集的方式就属于out-of-band策略
Dapper系统请求树树自身举行跟踪记载和收集带外数据。如许做是为两个不相关的缘故原由。起首,带内收集方案--这里跟踪数据会以RPC响应头的形式被返回--会影响应用程序网络动态。在Google里的许多规模较大的系统中,一次跟踪成千上万的span并不少见。然而,RPC回应大小--甚至是接近大型分布式的跟踪的根节点的这种情况下-- 仍旧是比较小的:通常小于10K。在这种情况下,带内Dapper的跟踪数据会让应用程序数据和倾向于利用后续分析结果的数据量相形见绌。其次,带内收集方案假定所有的RPC是完美嵌套的。我们发现,在所有的后端的系统返回的最闭幕果之前,有许多中心件会把结果返回给他们的调用者。带内收集系统是无法解释这种非嵌套的分布式执行模式的。
2.6 安全和隐私考虑
记载肯定量的RPC有效负载信息将丰富Dapper的跟踪能力,由于分析工具能够在有效载荷数据(方法通报的参数)中找到相关的样例,这些样例可以解释被监控系统的为何体现异常。然而,有些情况下,有效载荷数据可能包含的一些不应该透露给未经授权用户(包括正在debug的工程师)的内部信息。
由于安全和隐私题目是不可忽略的,dapper中的虽然存储RPC方法的名称,但在这个时间不记载任何有效载荷数据。相反,应用程序级别的Annotation提供了一个方便的可选机制:应用程序开发人员可以在span中选择关联那些为以后分析提供价值的数据。
Dapper还提供了一些安全上的便利,是它的计划者事先没有预料到的。通过跟踪公开的安全协议参数,Dapper可以通过相应级别的认证或加密,来监视应用程序是否满足安全策略。比方。Dapper还可以提供信息,以基于策略的的隔离系统按预期执行,比方支撑敏感数据的应用程序不与未经授权的系统组件举行了交互。如许的测算提供了比源码考核更强盛的保障。
3. Dapper部署状况
Dapper作为我们生产环境下的跟踪系统已经超过两年。在本节中,我们会陈诉系统状态,把重点放在Dapper如何满足了我们的目标——无处不在的部署和应用级的透明。
3.1 Dapper运行库
也许Dapper代码中中最关键的部分,就是对基础RPC、线程控制和流程控制的组件库的植入,此中包括span的创建,采样率的设置,以及把日记写入当地磁盘。除了做到轻量级,植入的代码更必要稳定和结实,由于它与海量的应用对接,维护和bug修复变得困难。植入的核心代码是由未超过1000行的C++和不超过800行Java代码构成。为了支持键值对的Annotation还添加了额外的500行代码。
3.2 生产环境下的涵盖面
Dapper的渗出可以总结为两个方面:一方面是可以创建Dapper跟踪的过程(与Dapper植入的组件库相关),和生产环境下的服务器上在运行Dapper跟踪收集守护进程。Dapper的守护进程的分布相称于我们服务器的简单的拓扑图,它存在于Google险些所有的服务器上。这很难确定精确的Dapper-ready进程部分,由于过程即便不产生跟踪信息Dapper也是无从知晓的。尽管如此,考虑到无处不在Dapper组件的植入库,我们估计险些每一个Google的生产进程都是支持跟踪的。
在某些情况下Dapper的是不能精确的跟踪控制路径的。这些通常源于利用非标准的控制流,或是Dapper的错误的把路径关联归到不相关的事件上。Dapper提供了一个简单的库来资助开发者手动控制跟踪传播作为一种变通方法。目前有40个C++应用程序和33个Java应用程序必要一些手动控制的追踪传播,不过这只是上千个的跟踪中的一小部分。也有非常小的一部分程序利用的非组件性子的通信库(比如原生的TCP Socket或SOAP RPC),因此不能直接支持Dapper的跟踪。但是这些应用可以单独接入到Dapper中,如果必要的话。
考虑到生产环境的安全,Dapper的跟踪也可以关闭。究竟上,它在部署的早起就是默认关闭的,直到我们对Dapper的稳定性和低消耗有了足够的信心之后才把它开启。Dapper的团队偶尔会执行审查探求跟踪设置的变化,来看看那些服务关闭了Dapper的跟踪。但这种情况不多见,而且通常是源于对监控对性能斲丧的担忧。经过了对实际性能斲丧的进一步观察和丈量,所有这些关闭Dapper跟踪都已经恢复开启了,不过这些已经不告急了。
3.3 跟踪Annotation的利用
程序员倾向于利用特定应用程序的Annotation,无论是作为一种分布式调试日记文件,还是通过一些应用程序特定的功能对跟踪举行分类。比方,所有的Bigtable的请求会把被访问的表名也记载到Annotation中。目前,70%的Dapper span和90%的所有Dapper跟踪都至少有一个特别应用的Annotation。
41个Java应用和68个C++应用中都添加自定义的Annotation为了更好地理解应用程序中的span在他们的服务中的行为。值得注意的是,迄今为止我们的Java开发者比C++开发者更多的在每一个跟踪span上接纳Annotation的API。这可能是由于我们的Java应用的作用域往往是更接近终极用户(C++偏底层);这些类型的应用程序常常处理更广泛的请求组合,因此具有比较复杂的控制路径。
4. 处理跟踪消耗
跟踪系统的成本由两部分构成:1.正在被监控的系统在生成追踪和收集追踪数据的斲丧导致系统性能降落,2。必要利用一部分资源来存储和分析跟踪数据。虽然你可以说一个有价值的组件植入跟踪带来一部分性能消耗是值得的,我们相信如果根本消耗能到达可以忽略的程度,那么对跟踪系统最初的推广会有极大的资助。
在本节中,我们会显现一下三个方面:Dapper组件操作的斲丧,跟踪收集的斲丧,以及Dapper对生产环境负载的影响。我们还介绍了Dapper可调治的采样率机制如何帮我们处理低消耗和跟踪代表性之间的平衡和弃取。
4.1 生成跟踪的消耗
生成跟踪的开销是Dapper性能影响中最关键的部分,由于收集和分析可以更轻易在紧急情况下被关闭。Dapper运行库中最告急的跟踪生成斲丧在于创建和销毁span和annotation,并记载到当地磁盘供后续的收集。根span的创建和销毁必要消耗平均204纳秒的时间,而同样的操作在其他span上必要斲丧176纳秒。时间上的差异重要在于必要在跟span上给这次跟踪分配一个全局唯一的ID。
如果一个span没有被采样的话,那么这个额外的span下创建annotation的成本险些可以忽略不计,他由在Dapper运行期对ThreadLocal查找操作构成,这平均只斲丧9纳秒。如果这个span被计入采样的话,会用一个用字符串举行标注--在图4中有显现--平均必要斲丧40纳秒。这些数据都是在2.2GHz的x86服务器上采集的。
在Dapper运行期写入到当地磁盘是最昂贵的操作,但是他们的可见消耗大大淘汰,由于写入日记文件和操作相对于被跟踪的应用系统来说都是异步的。不过,日记写入的操作如果在大流量的情况,尤其是每一个请求都被跟踪的情况下就会变得可以察觉到。我们记载了在4.3节展示了一次Web搜索的负载下的性能斲丧。
4.2 跟踪收集的斲丧
读出跟踪数据也会对正在被监控的负载产生干扰。表1展示的是最坏情况下,Dapper收集日记的守护进程在高于实际情况的负载基准下举行测试时的cpu利用率。在生产环境下,跟踪数据处理中,这个守护进程从来没有超过0.3%的单核cpu利用率,而且只有很少量的内存利用(以及堆碎片的噪音)。我们还限制了Dapper守护进程为内核scheduler最低的优先级,以防在一台高负载的服务器上发生cpu竞争。
Dapper也是一个带宽资源的轻量级的消费者,每一个span在我们的堆栈中传输只占用了平均426的byte。作为网络行为中的极小部分,Dapper的数据收集在Google的生产环境中的只占用了0.01%的网络资源。
4.3 在生产环境下对负载的影响
每个请求都会利用到大量的服务器的高吞吐量的线上服务,这是对有效跟踪最重要的需求之一;这种情况必要生成大量的跟踪数据,而且他们对性能的影响是最敏感的。在表2中我们用集群下的网络搜索服务作为例子,我们通过调整采样率,来衡量Dapper在延迟和吞吐量方面临性能的影响。
我们看到,虽然对吞吐量的影响不是很显着,但为了避免显着的延迟,跟踪的采样还是必要的。然而,延迟和吞吐量的带来的丧失在把采样率调整到小于1/16之后就全部在实验偏差范围内。在实践中,我们发现即便采样率调整到1/1024仍旧是有足够量的跟踪数据的用来跟踪大量的服务。保持Dapper的性能消耗基线在一个非常低的程度是很告急的,由于它为那些应用提供了一个宽松的环境利用完备的Annotation API而无惧性能丧失。利用较低的采样率另有额外的长处,可以让长期化到硬盘中的跟踪数据在垃圾回收机制处理之前保留更长的时间,如许为Dapper的收集组件给了更多的灵活性。
4.4 可变采样
任何给定进程的Dapper的斲丧和每个进程单位时间的跟踪的采样率成正比。Dapper的第一个生产版本在Google内部的所有进程上利用统一的采样率,为1/1024。这个简单的方案是对我们的高吞吐量的线上服务来说优劣常有用,由于那些感兴趣的事件(在大吞吐量的情况下)仍旧很有可能常常出现,而且通常足以被捕捉到。
然而,在较低的采样率和较低的传输负载下可能会导致错过告急事件,而想用较高的采样率就必要能接受的性能消耗。对于如许的系统的办理方案就是覆盖默认的采样率,这必要手动干预的,这种情况是我们试图避免在dapper中出现的。
我们在部署可变采样的过程中,参数化设置采样率时,不是利用一个统一的采样方案,而是利用一个采样盼望率来标识单位时间内采样的追踪。如许一来,低流量低负载主动提高采样率,而在高流量高负载的情况下会降低采样率,使消耗一直保持在控制之下。实际利用的采样率会随着跟踪自己记载下来,这有利于从Dapper的跟踪数据中正确的分析。
4.5 应对积极采样(Coping with aggressive sampling)
新的Dapper用户往往觉得低采样率--在高吞吐量的服务下常常低至0.01%--将会不利于他们的分析。我们在Google的履历使我们相信,对于高吞吐量服务,积极采样(aggressive sampling)并不妨碍最告急的分析。如果一个显着的操作在系统中出现一次,他就会出现上千次。低吞吐量的服务--也许是每秒请求几十次,而不是几十万--可以负担得起跟踪每一个请求,这是促使我们下刻意利用自适应采样率的缘故原由。
4.6 在收集过程中额外的采样
上述采样机制被计划为尽量淘汰与Dapper运行库协作的应用程序中显着的性能消耗。Dapper的团队还必要控制写入中心资料库的数据的总规模,因此为到达这个目的,我们联合了二级采样。
目前我们的生产集群每天产生超过1TB的采样跟踪数据。Dapper的用户希望生产环境下的进程的跟踪数据从被记载之后能保存至少两周的时间。徐徐增长的追踪数据的密度必须和Dapper中心堆栈所斲丧的服务器及硬盘存储举行权衡。对请求的高采样率还使得Dapper收集器接近写入吞吐量的上限。
为了维持物质资源的需求和渐增的Bigtable的吞吐之间的灵活性,我们在收集系统自身上增加了额外的采样率的支持。我们充分利用所有span都来自一个特定的跟踪并分享同一个跟踪ID这个究竟,虽然这些span有可能横跨了数千个主机。对于在收集系统中的每一个span,我们用hash算法把跟踪ID转成一个标量Z,这里0<=Z<=1。如果Z比我们收集系统中的系数低的话,我们就保留这个span信息,并写入到Bigtable中。反之,我们就抛弃他。通过在采样决策中的跟踪ID,我们要么保存、要么抛弃整个跟踪,而不是单独处理跟踪内的span。我们发现,有了这个额外的设置参数使管理我们的收集管道变得简单多了,由于我们可以很轻易地在设置文件中调整我们的全局写入率这个参数。
如果整个跟踪过程和收集系统只利用一个采样率参数确实会简单一些,但是这就不能应对快速调整在所有部署的节点上的运行期采样率设置的这个要求。我们选择了运行期采样率,如许就可以优雅的去掉我们无法写入到堆栈中的多余数据,我们还可以通过调治收集系统中的二级采样率系数来调整这个运行期采样率。Dapper的管道维护变得更轻易,由于我们就可以通过修改我们的二级采样率的设置,直接增加或淘汰我们的全局覆盖率和写入速度。
5. 通用的Dapper工具
几年前,当Dapper还只是个原型的时间,它只能在Dapper开发者耐烦的支持下利用。从那时起,我们徐徐迭代的建立了收集组件,编程接口,和基于Web的交互式用户界面,资助Dapper的用户独立办理自己的题目。在本节中,我们会总结一下哪些的方法有用,哪些用处不大,我们还提供关于这些通用的分析工具的根本的利用信息。
5.1 Dapper Depot API
Dapper的“Depot API”或称作DAPI,提供在Dapper的地域堆栈中对分布式跟踪数据一个直接访问。DAPI和Dapper跟踪堆栈被计划成串联的,而且DAPI意味着对Dapper堆栈中的元数据袒露一个干净和直观的的接口。我们利用了以下推荐的三种方式去袒露如许的接口:
- 通过跟踪ID来访问:DAPI可以通过他的全局唯一的跟踪ID读取任何一次跟踪信息。
- 批量访问:DAPI可以利用的MapReduce提供对上亿条Dapper跟踪数据的并行读取。用户重写一个假造函数,它接受一个Dapper的跟踪信息作为其唯一的参数,该框架将在用户指定的时间窗口中调用每一次收集到的跟踪信息。
- 索引访问:Dapper的堆栈支持一个符合我们通用调用模板的唯一索引。该索引根据通用请求跟踪特性(commonly-requested trace features)举行绘制来识别Dapper的跟踪信息。由于跟踪ID是根据伪随机的规则创建的,这是最好的办法去访问跟某个服务或主机相关的跟踪数据。
所有这三种访问模式把用户指向差异的Dapper跟踪记载。正如第2.1节所述的,Dapper的由span构成的跟踪数据是用树形布局建模的,因此,跟踪数据的数据布局,也是一个简单的由span构成遍历树。Span就相称于RPC调用,在这种情况下,RPC的时间信息是可用的。带时间戳的特别的应用标注也是可以通过这个span布局来访问的。
选择一个合适的自定义索引是DAPI计划中最具挑战性的部分。压缩存储要求在跟踪数据种建立一个索引的情况只比实际数据小26%,以是斲丧是巨大的。最初,我们部署了两个索引:第一个是主机索引,另一个是服务名的索引。然而,我们并没有找到主机索引和存储成本之间的利害关系。当用户对每一台主机感兴趣的时间,他们也会对特定的服务感兴趣,以是我们终极选择把两者相联合,成为一个组合索引,它答应以服务名称,主机,和时间戳的序次举行有效的查找。
5.1.1 DAPI在Google内部的利用
DAPI在谷歌的利用有三类:使利用DAPI的持续的线上Web应用,维护精良的可以在控制台上调用的基于DAPI的工具,可以被写入,运行、不过大部分已经被忘记了的一次性分析工具。我们知道的有3个长期性的基于DAPI的应用程序,8个额外的按需定制的基于DAPI分析工具,以及利用DAPI框架构建的约15~20一次性的分析工具。在这之后的工具就这是很难阐明了,由于开发者可以构建、运行和抛弃这些项目,而不必要Dapper团队的技能支持。
5.2 Dapper的用户接口
绝大多数用户利用发生在基于web的用户交互接口。篇幅有限,我们不能列出每一个特点,而只能把典型的用户工作流在图6中展示。
- 用户描述的他们关心的服务和时间,和其他任何他们可以用来区分跟踪模板的信息(比如,span的名称)。他们还可以指定与他们的搜索最相关的成本度量(cost metric)(比如,服务响应时间)。
- 一个关于性能概要的大表格,对应确定的服务关联的所有分布式处理图表。用户可以把这些执行图标排序成他们想要的,并选择一种直方图去显现出更多的细节。
- 一旦某个单一的分布式执行部分被选中后,用户能看到关于执行部分的的图形化描述。被选中的服务被高亮展示在该图的中心。
- 在生成与步骤1中选中的成本度量(cost metric)维度相关的统计信息之后,Dapper的用户界面会提供了一个简单的直方图。在这个例子中,我们可以看到一个大致的所选中部分的分布式响应时间分布图。用户还会看到一个关于具体的跟踪信息的列表,显现跟踪信息在直方图中被划分为的差异地域。在这个例子中,用户点击列表种第二个跟踪信息实例时,会在下方看到这个跟踪信息的详细视图(步骤5)。
- 绝大多数Dapper的利用者终极的会检查某个跟踪的情况,希望能收集一些信息去相识系统行为的根源地点。我们没有足够的空间来做跟踪视图的审查,但我们利用由一个全局时间轴(在上方可以看到),并能够睁开和折叠树形布局的交互方式,这也很有特点。分布式跟踪树的连续层用内嵌的差异颜色的矩形体现。每一个RPC的span被从时间上分解为一个服务器进程中的斲丧(绿色部分)和在网络上的斲丧(蓝色部分)。用户Annotation没有显示在这个截图中,但他们可以选择性的以span的形式包含在全局时间轴上。
为了让用户查询及时数据,Dapper的用户界面能够直接与Dapper每一台生产环境下的服务器上的守护进程举行交互。在该模式下,不可能指望能看到上面所说的系统级的图表展示,但仍旧可以很轻易基于性能和网络特性选取一个特定的跟踪。在这种模式下,可在几秒钟内查到及时的数据。
根据我们的记载,大约有200个差异的Google工程师在一天内利用的Dapper的UI;在一周的过程中,大约有750-1000差异的用户。这些用户数,在新功能的内部告示上,是按月连续的。通常用户会发送特定跟踪的毗连,这将不可避免地在查询跟踪情况时中产生很多一次性的,持续时间较短的交互。
6. 履历
Dapper在Google被广泛应用,一部分直接通过Dapper的用户界面,另一部分间接地通过对Dapper API的二次开发或者建立在基于api的应用上。在本节中,我们并不计划罗列出每一种已知的Dapper利用方式,而是试图覆盖Dapper利用方式的“根本向量”,并积极来阐明什么样的应用是最成功的。
6.1 在开发中利用Dapper
Google AdWords系统是围绕一个大型的关键词定位准则和相关笔墨广告的数据库搭建的。当新的关键字或广告被插入或修改时,它们必须通过服务策略术语的检查(如检查不得当的语言,这个过程如果利用主动复查系统来做的话会更加有效)。
当轮到从头重新计划一个广告审查服务时,这个团队迭代的从第一个系统原型开始利用Dapper,而且,终极用Dapper一直维护着他们的系统。Dapper资助他们从以下几个方面改进了他们的服务:
- 性能:开发人员针对请求延迟的目标举行跟踪,并对轻易优化的地方举行定位。Dapper也被用来确定在关键路径上不必要的串行请求--通常来源于不是开发者自己开发的子系统--并促使团队持续修复他们。
- 精确性:广告审查服务围绕大型数据库系统搭建。系统同时具有只读副本策略(数据访问便宜)和读写的主策略(访问代价高)。Dapper被用来在很多种情况中确定,哪些查询是无需通过主策略访问而可以接纳副本策略访问。Dapper如今可以负责监控哪些主策略被直接访问,并对告急的系统常量举行保障。
- 理解性:广告审查查询跨越了各种类型的系统,包括BigTable—之前提到的那个数据库,多维索引服务,以及其他各种C++和Java后端服务。Dapper的跟踪用来评估总查询成本,促进重新对业务的计划,用以在他们的系统依靠上淘汰负载。
- 测试:新的代码版本会经过一个利用Dapper举行跟踪的QA过程,用来验证精确的系统行为和性能。在跑测试的过程中能发现很多题目,这些题目来自广告审查系统自身的代码或是他的依靠包。
广告审查团队广泛利用了Dapper Annotation API。Guice[13]开源的AOP框架用来在告急的软件组件上标注“@Traced”。这些跟踪信息可以进一步被标注,包含:告急子路径的输入输出大小、基础信息、其他调试信息,所有这些信息将会额外发送到日记文件中。
同时,我们也发现了一些广告审查小组在利用方面的不足。比如:他们想根据他们所有跟踪的Annotation信息,在一个交互时间段内举行搜索,然而这就必须跑一个自定义的MapReduce或举行每一个跟踪的手动检查。另外,在Google另有一些其他的系统在也从通用调试日记中收集和集中信息,把那些系统的海量数据和Dapper堆栈整合也是有价值的。
总的来说,即便如此,广告审查团队仍旧对Dapper的作用举行了以下评估,通过利用Dapper的跟踪平台的数据分析,他们的服务延迟性已经优化了两个数量级。
6.1.1 与异常监控的集成
Google维护了一个从运行进程中不断收集并集中异常信息陈诉的服务。如果这些异常发生在Dapper跟踪采样的上下文中,那么相应的跟踪ID和span的ID也会作为元数据记载在异常陈诉中。异常监测服务的前端会提供一个链接,从特定的异常信息的陈诉直接导向到他们各自的分布式跟踪。广告审查团队利用这个功能可以相识bug发生的更大范围的上下文。通过袒露基于简单的唯一ID构建的接口,Dapper平台被集成到其他事件监测系统会相对轻易。
6.2 办理延迟的长尾效应
考虑到移动部件的数量、代码库的规模、部署的范围,调试一个像全文搜索那样服务(第1节里提到过)优劣常具有挑战性的。在这节,我们描述了我们在减轻全文搜索的延迟分布的长尾效应上做的各种积极。Dapper能够验证端到端的延迟的假设,更具体地说,Dapper能够验证对于搜索请求的关键路径。当一个系统不仅涉及数个子系统,而是几十个开发团队的涉及到的系统的情况下,端到端性能较差的根本缘故原由到底在哪,这个题目纵然是我们最好的和最有履历的工程师也无法精确回复。在这种情况下,Dapper可以提供急需的数据,而且可以对许多告急的性能题目得出结论。
在调试延迟长尾效应的过程中,工程师可以建立一个小型库,这个小型库可以根据DAPI跟踪对象来推断关键路径的层级布局。这些关键路径的布局可以被用来诊断题目,而且为全文搜索提供可优先处理的预期的性能改进。Dapper的这项工作导致了下列发现:
- 在关键路径上的短暂的网络性能退化不影响系统的吞吐量,但它可能会对延迟异常值产生极大的影响。在图7中可以看出,大部分的全局搜索的缓慢的跟踪都来源于关键路径的网络性能退化。
- 许多题目和代价很高的查询模式来源于一些意想不到的服务之间的交互。一旦发现,往往轻易纠正它们,但是Dapper出现之前想找出这些题目是相称困难的。
- 通用的查询从Dapper之外的安全日记堆栈中收取,并利用Dapper唯一的跟踪ID,与Dapper的堆栈做关联。然后,该映射用来建立关于在全局搜索中的每一个独立子系统都很慢的实例查询的列表。
6.3 推断服务依靠
在任何给定的时间内,Google内部的一个典型的计算集群是一个搜集了成千上万个逻辑“任务”的主机,一套的处理器在执行一个通用的方法。Google维护着许多如许的集群,当然,究竟上,我们发如今一个集群上计算着的这些任务通常依靠于其他的集群上的任务。由于任务们之间的依靠是动态改变的,以是不可能仅从设置信息上推断出所有这些服务之间的依靠关系。不过,除了其他方面的缘故原由之外,在公司内部的各个流程必要正确的服务依靠关系信息,以确定瓶颈地点,以及计划服务的迁徙。Google的可称为“Service Dependencies”的项目是通过利用跟踪Annotation和DAPI MapReduce接口来实现主动化确定服务依靠归属的。
Dapper核心组件与Dapper跟踪Annotation一并利用的情况下,“Service Dependencies”项目能够推算出任务各自之间的依靠,以及任务和其他软件组件之间的依靠。比如,所有的BigTable的操作会加上与受影响的表名称相关的标记。运用Dapper的平台,Service Dependencies团队就可以主动的推算出依靠于定名的差异资源的服务粒度。
6.4 差异服务的网络利用率
Google投入了大量的人力和物力资源在他的网络布局上。从前网络管理员可能只关注独立的硬件信息、常用工具及以及搭建出的各种全局网络鸟瞰图的dashboard上的信息。网络管理员确实可以一览整个网络的康健状况,但是,当碰到题目时,他们很少有能够正确查找网络负载的工具,用来定位应用程序级别的罪魁罪魁。
虽然Dapper不是计划用来做链路级的监控的,但是我们发现,它优劣常适合去做集群之间网络运动性的应用级任务的分析。Google能够利用Dapper这个平台,建立一个不断更新的控制台,来显示集群之间最活泼的网络流量的应用级的热点。别的,利用Dapper我们能够为昂贵的网络请求提供指出的构成缘故原由的跟踪,而不是面临差异服务器之间的信息孤岛而无所适从。建立一个基于Dapper API的dashboard总共没花超过2周的时间。
6.5 分层和共享存储系统
在Google的许多存储系统是由多重独立复杂层级的分布式基础设备构成的。比方,Google的App Engine[5]就是搭建在一个可扩展的实体存储系统上的。该实体存储系统在基于BigTable上公开某些RDBMS功能。 BigTable的同时利用Chubby[7](分布式锁系统)及GFS。再者,像BigTable如许的系统简化了部署,并更好的利用了计算资源。
在这种分层的系统,并不总是很轻易确定终极用户资源的消费模式。比方,来自于一个给定的BigTable单位格的GFS大信息量重要来自于一个用户或是由多个用户产生,但是在GFS层面,这两种显着的利用场景是很难界定。而且,如果缺乏一个像Dapper一样的工具的情况下,对共享服务的竞争可能会同样难于调试。
第5.2节中所示的Dapper的用户界面可以聚合那些调用任意公共服务的多个客户端的跟踪的性能信息。这就很轻易让提供这些服务的源从多个维度给他们的用户排名。(比方,入站的网络负载,出站的网络负载,或服务请求的总时间)
6.6 Dapper的救火能力(Firefighting)
对于一些“救火”任务,Dapper可以处理此中的一部分。“救火”任务在这里是指一些有风险很高的在分布式系统上的操作。通常情况下,Dapper用户当正在举行“救火”任务时必要利用新的数据,而且没有时间写新的DAPI代码或等待周期性的陈诉运行。
对于那些高延迟,不,可能更糟糕的那些在正常负载下都会响应超时的服务,Dapper用户界面通常会把这些延迟瓶颈的位置隔离出来。通过与Dapper守护进程的直接通信,那些特定的高延迟的跟踪数据轻易的收集到。当出现灾难性故障时,通常是没有必要去看统计数据以确定根本缘故原由,只查看示例跟踪就足够了(由于前文提到过从Dapper守护进程中险些可以立即得到跟踪数据)。
但是,如在6.5节中描述的共享的存储服务,要求当用户运动过程中突然停止时能尽可能快的汇总信息。对于事件发生之后,共享服务仍旧可以利用汇总的的Dapper数据,但是,除非收集到的Dapper数据的批量分析能在题目出现10分钟之内完成,否则Dapper面临与共享存储服务相关的“救火”任务就很难按预想的那般顺遂完成。
7. 其他收获
虽然迄今为止,我们在Dapper上的履历已经大致符合我们的预期,但是也出现了一些积极的方面是我们没有充分预料到的。起首,我们得到了超出预期的Dapper利用用例的数量,对此我们可谓欢心鼓舞。另外,在除了几个的在第6节利用履历中提到过的一些用例之外,还包括资源核算系统,对指定的通讯模式敏感的服务的检查工具,以及一种对RPC压缩策略的分析器,等等。我们认为这些意想不到的用例肯定程度上是由于我们向开发者以一种简单的编程接口的方式开放了跟踪数据存储的缘故,这使得我们能够充分利用这个大的多的社区的创造力。除此之外,Dapper对旧的负载的支持也比预期的要简单,只必要在程序中引入一个用新版本的重新编译过的公共组件库(包含通例的线程利用,控制流和RPC框架)即可。
Dapper在Google内部的广泛利用还为我们在Dapper的范围性上提供了宝贵的反馈意见。下面我们将介绍一些我们已知的最告急的Dapper的不足:
- 合并的影响:我们的模型隐含的前提是差异的子系统在处理的都是来自同一个被跟踪的请求。在某些情况下,缓冲一部分请求,然后一次性操作一个请求集会更加有效。(比如,磁盘上的一次合并写入操作)。在这种情况下,一个被跟踪的请求可以看似是一个大型工作单位。别的,当有多个追踪请求被收集在一起,他们当中只有一个会用来生成那个唯一的跟踪ID,用来给其他span利用,以是就无法跟踪下去了。我们正在考虑的办理方案,希望在可以识别这种情况的前提下,用尽可能少的记载来办理这个题目。
- 跟踪批处理负载:Dapper的计划,重要是针对在线服务系统,最初的目标是相识一个用户请求产生的系统行为。然而,离线的密集型负载,比方符合MapReduce[10]模型的情况,也可以受益于性能挖潜。在这种情况下,我们必要把跟踪ID与一些其他的有意义的工作单位做关联,诸如输入数据中的键值(或键值的范围),或是一个MapReduce shard。
- 探求根源:Dapper可以有效地确定系统中的哪一部分致使系统整个速度变慢,但并不总是能够找出题目的根源。比方,一个请求很慢有可能不是由于它自己的行为,而是由于队列中其他排在它前面的(queued ahead of)请求还没处理完。程序可以利用应用级的annotation把队列的大小或过载情况写入跟踪系统。别的,如果这种情况屡见不鲜,那么在ProfileMe[11]中提到的成对的采样技能可以办理这个题目。它由两个时间重叠的采样率构成,并观察它们在整个系统中的相对延迟。
- 记载内核级的信息:一些内核可见的事件的详细信息有时对确定题目根源是很有用的。我们有一些工具,能够跟踪或以其他方式描述内核的执行,但是,想用通用的或是不那么突兀的方式,是很难把这些信息到捆绑到用户级别的跟踪上下文中。我们正在研究一种妥协的办理方案,我们在用户层面上把一些内核级的运动参数做快照,然后绑定他们到一个运动的span上。
8. 相关产品
在分布式系统跟踪领域,有一套完备的体系,一部分系统重要关注定位到故障位置,其他的目标是针对性能举行优化。 Dapper确实被用于发现系统题目,但它更通常用于探查性能不足,以及提高全面大规模的工作负载下的系统行为的理解。
与Dapper相关的黑盒监控系统,比如Project5[1],WAP5[15]和Sherlock[2],可以说不依靠运行库的情况下,黑盒监控系统能够实现更高的应用级透明。黑盒的缺点是肯定程度上不够精确,并可能在统计推断关键路径时带来更大的系统消耗。
对于分布式系统监控来说,基于Annotation的中心件或应用自身是一个可能是更受接待的办理办法.拿Pip[14]和Webmon[16]系统举例,他们更依靠于应用级的Annotation,而X-Trace[12],Pinpoint[9]和Magpie[3]大多集中在对库和中心件的修改。Dapper更接近后者。像Pinpoint,X-Trace,和早期版本的Magpie一样,Dapper接纳了全局标识符把分布式系统中各部分相关的事件联系在一起。和这些系统类似,Dapper实验避免利用应用级Annotation,而是把的植入隐藏在通用组件模块内。Magpie放弃利用全局ID,仍旧试图精确的完成请求的精确传播,他通过接纳应用系统各自写入的事件策略,终极也能精确描述差异事件之间关系。但是目前还不清楚Magpie在实际环境中实现透明性这些策略到底多么有效。 X-Trace的核心Annotation比Dapper更有野心一些,由于X-Trace系统对于跟踪的收集,不仅在跟踪节点层面上,而且在节点内部差异的软件层也会举行跟踪。而我们对于组件的低性能消耗的要求迫使我们不能接纳X-Trace如许的模型,而是朝着把一个请求毗连起来完备跟踪所能做到的最小代价而积极。而Dapper的跟踪仍旧可以从可选的应用级Annotation中获益。
9. 总结
在本文中,我们介绍Dapper这个Google的生产环境下的分布式系统跟踪平台,并陈诉了我们开发和利用它的相关履历。 Dapper险些在部署在所有的Google系统上,并可以在不必要应用级修改的情况下举行跟踪,而且没有显着的性能影响。Dapper对于开发人员和运维团队带来的长处,可以从我们重要的跟踪用户界面的广泛利用上看出来,另外我们还列举了一些Dapper的利用用例来阐明Dapper的作用,这些用例有些甚至都没有Dapper开发团队到场,而是被应用的开发者开发出来的。
据我们所知,这是第一篇陈诉生产环境下分布式系统跟踪框架的论文。究竟上,我们的重要贡献源于这个究竟:论文中回首的这个系统已经运行两年之久。我们发现,联合对开发人员提供简单API和对应用系统完全透明来增强跟踪的这个决定,优劣常值得的。
我们相信,Dapper比以前的基于Annotation的分布式跟踪到达更高的应用透明度,这一点已经通过只必要少量人工干预的工作量得以证实。虽然肯定程度上得益于我们的系统的同质性,但它自己仍旧是一个重大的挑战。最告急的是,我们的计划提出了一些实现应用级透明性的充分条件,对此我们希望能够对更错杂环境下的办理方案的开发有所资助。
最后,通过开放Dapper跟踪堆栈给内部开发者,我们促使更多的基于跟踪堆栈的分析工具的产生,而仅仅由Dapper团队默默的在信息孤岛中笃志苦干的结果远达不到如今这么大的规模,这个决定促使了计划和实施的睁开。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |