大数跨境
0
0

Dapper:谷歌的大规模分布式跟踪系统(下)

Dapper:谷歌的大规模分布式跟踪系统(下) 数据分析与开发
2016-02-16
1
导读:(点击上方公号,可快速关注)英文:Research at Google译者:bigbully网址:http:

(点击上方公号,可快速关注)


英文:Research at Google

译者:bigbully

网址:http://bigbully.github.io/Dapper-translation/


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中展示。


图6


  1. 用户描述的他们关心的服务和时间,和其他任何他们可以用来区分跟踪模板的信息(比如,span的名称)。他们还可以指定与他们的搜索最相关的成本度量(cost metric)(比如,服务响应时间)。


  2. 一个关于性能概要的大表格,对应确定的服务关联的所有分布式处理图表。用户可以把这些执行图标排序成他们想要的,并选择一种直方图去展现出更多的细节。


  3. 一旦某个单一的分布式执行部分被选中后,用户能看到关于执行部分的的图形化描述。被选中的服务被高亮展示在该图的中心。


  4. 在生成与步骤1中选中的成本度量(cost metric)维度相关的统计信息之后,Dapper的用户界面会提供了一个简单的直方图。在这个例子中,我们可以看到一个大致的所选中部分的分布式响应时间分布图。用户还会看到一个关于具体的跟踪信息的列表,展现跟踪信息在直方图中被划分为的不同区域。在这个例子中,用户点击列表种第二个跟踪信息实例时,会在下方看到这个跟踪信息的详细视图(步骤5)。


  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开源的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可以提供急需的数据,而且可以对许多重要的性能问题得出结论。


图7:全局搜索的跟踪片段,在不常遇到高网络延迟的情况下,在沿着关键路径的端到端的请求延迟,如图所示。


在调试延迟长尾效应的过程中,工程师可以建立一个小型库,这个小型库可以根据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就是搭建在一个可扩展的实体存储系统上的。该实体存储系统在基于BigTable上公开某些RDBMS功能。 BigTable的同时使用Chubby(分布式锁系统)及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模型的情况,也可以受益于性能挖潜。在这种情况下,我们需要把跟踪ID与一些其他的有意义的工作单元做关联,诸如输入数据中的键值(或键值的范围),或是一个MapReduce shard。


  • 寻找根源:Dapper可以有效地确定系统中的哪一部分致使系统整个速度变慢,但并不总是能够找出问题的根源。例如,一个请求很慢有可能不是因为它自己的行为,而是由于队列中其他排在它前面的(queued ahead of)请求还没处理完。程序可以使用应用级的annotation把队列的大小或过载情况写入跟踪系统。此外,如果这种情况屡见不鲜,那么在ProfileMe中提到的成对的采样技术可以解决这个问题。它由两个时间重叠的采样率组成,并观察它们在整个系统中的相对延迟。


  • 记录内核级的信息:一些内核可见的事件的详细信息有时对确定问题根源是很有用的。我们有一些工具,能够跟踪或以其他方式描述内核的执行,但是,想用通用的或是不那么突兀的方式,是很难把这些信息到捆绑到用户级别的跟踪上下文中。我们正在研究一种妥协的解决方案,我们在用户层面上把一些内核级的活动参数做快照,然后绑定他们到一个活动的span上。


8. 相关产品


在分布式系统跟踪领域,有一套完整的体系,一部分系统主要关注定位到故障位置,其他的目标是针对性能进行优化。 Dapper确实被用于发现系统问题,但它更通常用于探查性能不足,以及提高全面大规模的工作负载下的系统行为的理解。


与Dapper相关的黑盒监控系统,比如Project5,WAP5和Sherlock,可以说不依赖运行库的情况下,黑盒监控系统能够实现更高的应用级透明。黑盒的缺点是一定程度上不够精确,并可能在统计推断关键路径时带来更大的系统损耗。


对于分布式系统监控来说,基于Annotation的中间件或应用自身是一个可能是更受欢迎的解决办法.拿Pip和Webmon系统举例,他们更依赖于应用级的Annotation,而X-Trace,Pinpoint和Magpie大多集中在对库和中间件的修改。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团队默默的在信息孤岛中埋头苦干的结果远达不到现在这么大的规模,这个决定促使了设计和实施的展开。



【今日微信账号推荐】

【声明】内容源于网络
0
0
数据分析与开发
「数据分析与开发」分享数据分析与开发相关技术文章、教程、工具
内容 2105
粉丝 0
数据分析与开发 「数据分析与开发」分享数据分析与开发相关技术文章、教程、工具
总阅读698
粉丝0
内容2.1k