Dapper最初是为了追踪在线服务系统的请求处理过程。比如在搜索系统中,用户的一个请求在系统中会经过多个子系统的处理,而且这些处理是发生在不同机器甚至是不同集群上的,当请求处理发生异常时,需要快速发现问题,并准确定位到是哪个环节出了问题,这是非常重要的,Dapper就是为了解决这样的问题。
对系统行为进行跟踪必须是持续进行的,因为异常的发生是无法预料的,而且可能是难以重现的。同时跟踪需要是无所不在,遍布各处的,否则可能会遗漏某些重要的点。基于此Dapper有如下三个最重要的设计目标:低的额外开销,对应用的透明性,可扩展。同时产生的跟踪数据需要可以被快速分析,这样可以帮助用户实时获取在线服务状态。
实现方法
低的额外开销:不是对所有的请求进行跟踪而是要采样,收集跟踪数据时进行二次采样
对应用的透明性:修改多线程,控制流,RPC等基础库代码,插入负责跟踪的代码。在Google,应用使用的是相同的多线程,控制流,RPC等基础库代码,所以仅通过修改它们就可以实现跟踪功能。当线程进行一个被跟踪的处理时,Dapper会将一个trace context关联到线程本地化存储中。trace context中包含了span相关属性,比如trace和span id。对于需要进行异步处理的情况,Google开发者通常都会采用一个通用的控制流库来实现回调,并将它们调度到一个线程池或是执行器中调用。Dapper保证所有回调都会保存它们创建者的trace context,同时在该回调被调用时该trace context也会被关联到对应线程。这样,Dapper就可以实现这种异步处理过程的跟踪。对于被跟踪的RPC调用,span和trace id也会跟着被从客户端传到服务端。从功能上看这部分代码主要包括span的创建,采样,本地磁盘日志写入,但是因为它会被很多应用所依赖,维护和bug fix难度高,需要非常高的稳定性和健壮性。同时还要轻量,实际上这部分代码的C++实现也总共不到1000行。
Dapper支持用户直接获取Tracer对象,并输出自己的自定义信息,用户可以输出自己任意想输出的内容,为防止用户过度输出,提供用户可配置参数来控制其上限。
跟踪时需要对请求进行标记,会产生一个唯一ID(在Dapper中是一个64位整数)用来标识该请求。对于Dapper来说,一个trace(跟踪过程)实际上是一颗树,树中的节点被称为一个span,根节点被称为root span。如下图所述:
需要注意的是一个span可能包含来自多个主机的信息;实际上每个RPC span包含了来自客户端和服务端的信息。但是客户端和服务端的时钟是有偏差的,文中并未指明如何解决这个问题,只是说可以利用如下事实"RPC的发起客户端是在服务端接收到前进行地,针对该RPC的响应则是由服务端在客户端收到前发出的",确定时间戳的一个上下界。
Dapper的整个数据收集过程如下图所示:首先将span数据写入本地日志文件,然后将数据收集并写入Bigtable,每个trace记录将会被作为表中的一行,Bigtable的稀疏表结构非常适合存储trace记录,因为每条记录可能有任意个的span。整个收集过程是out-of-band的,与请求处理是完全不相干的两个独立过程,这样就不会影响到请求的处理。如果改成in-band的,即将trace数据与RPC响应报文一块发送回来,会影响到应用的网络状况,同时RPC调用也有可能不是完美嵌套的,某些RPC调用可能会在它本身依赖的那些返回前就提前返回了。
Dapper提供API允许用户直接访问这些跟踪数据。Google内部开发人员可以基于这些API开发通用的或者面向具体应用的分析工具。这一点,对于提高Dapper的作用和影响力起到了出人意料的效果。
跟踪开销
如果跟踪带来的额外开销太高,用户通常会选择关掉它,因此低开销非常重要。采样可以降低开销,但是简单的采样可能导致采样结果无代表性,Dapper通过采用自适应的采样机制来满足性能和代表性两方面的需求。
trace的生成开销对Dapper来说是最关键的,因为数据的收集和分析可以临时关掉,只要数据一直生成就可以后面再进行收集分析。在trace生成中,最大头的地方在于span和annotation的创建和销毁上。根span的创建和销毁平均需要204ns,普通span只需要176ns,区别在于根span需要产生一个全局唯一的trace id。如果span没有被采样到,那么对它添加annotation的开销基本可忽略,大概需要9ns。但是如果是被采样到的话,那么平均开销是40ns。这些测试是在一个2.2GHZ的x86服务器上进行的。本地磁盘写入是Dapper运行库中最昂贵的操作,但是它们可以异步化,批量化,因此它们基本上只会影响到那些高吞吐率的应用。
将跟踪数据通过Dapper后台进程读出也会产生一些开销。但是根据我们的观察,Dapper daemon的CPU开销始终在0.3%之下,内存占用也很少,此外也会带来轻量的网络开销,但是每个span平均只有426字节大小,网络开销只占了整个产品系统流量的0.01%不到。
对于那些每个请求都可能产生大量跟踪数据的应用来说,我们还会通过采样来降低开销。我们通过保证跟踪开销可以始终保持在很低的水平上,使得用户可以放心大胆的使用它。最初我们的采样策略很简单,是在每1024个请求中选择一个进行跟踪,这种模式对于那种请求量很高的服务来说,可以保证跟踪到有价值的信息,但是对于那些负载不高的服务来说,可能会导致采样频率过低,从而遗漏重要信息。因此我们决定以时间为采样单位,保证单位时间内可以进行固定次数的采样,这样采样频率和开销都更好控制了。
应用
用户可以通过DAPI(Dapper“Depot API”)直接访问跟踪数据。DAPI提供如下几种访问方式:指定trace id进行访问;大规模批量访问,用户可以通过MapReduce job并行访问,用户只需要实现一个以Dapper trace为参数的虚函数,在该函数内完成自己的处理即可,框架负责为用户指定时间段内的所有trace调用该函数;通过索引进行访问,Dapper会为跟踪数据建立索引,用户可通过索引进行查询,因为trace id是随机生成的,因此用户通常需要通过服务名或机器名进行检索(实际上Dapper是按照(服务名,机器名,时间戳)进行索引的)。
大部分用户都是通过一个交互式web接口来使用Dapper的,典型流程如下图所示:
1.用户输入他感兴趣的服务和时间窗口,选择相应跟踪模式(这里是span名称),以及他最关心的某个度量参数(这里是服务延迟)
2.页面上会展示一个指定服务的所有分布式执行过程的性能摘要,用户可能会对这些执行过程根据需要进行排序,然后选择一个详细看
3.一旦用户选定了某个执行过程后,将会有一个关于该执行过程的图形化描述展现出来,用户可以点击选择自己关心的那个过程
4.系统根据用户在1中选择的度量参数,以及3中选择的具体过程,显示一个直方图。在这里显示的是有关getdocs的延迟分布的直方图,用户可以点击右侧的example,选择具体的一个执行过程进行查看
5.显示关于该执行过程的具体信息,上方是一个时间轴,下方用户可以进行展开或折叠,查看该执行过程各个组成部分的开销,其中绿色代表处理时间,蓝色代表花在网络上的时间。
经验教训
在开发过程中使用Dapper,可以帮助用户提高性能(分析请求延迟,发现关键路径上不必要的串行化),进行正确性检查(用户请求是否正确发送给了服务提供者),理解系统(请求处理可能依赖很多其他系统,Dapper帮助用户了解总体延迟,重新设计最小化依赖),测试(新代码release前要通过一个Dapper跟踪测试,验证系统行为和性能)。比如,通过使用Dapper,Ads Review团队将延迟降低了两个数量级。
同时我们还将跟踪系统与异常监控系统进行集成,如果异常发生在一个采样到的Dapper tracer上下文中,那么相应的trace和span id还会被作为异常报告的元数据,前端的异常监控服务还会提供相应链接指向跟踪系统。这样可以帮助用户了解异常发生时的情况。
解决长尾延迟,帮助用户分析复杂系统环境下的延迟问题。网络性能的瞬时下降不会影响系统的吞吐率,但是对延迟有很大影响。很多开销昂贵的查询模式是由于未预料到的服务间的交互造成的,Dapper的出现使得这种问题的发现变得非常容易。
帮助用户进行服务间依赖的推理。Google维护了非常多的集群,每个集群上承载了各种各样的任务,而任务间可能存在依赖关系。但是各个任务需要精确知道它所依赖的服务信息,以帮助发现瓶颈或进行服务的移动。服务间的依赖是复杂的而且是动态的,单纯依赖配置文件很难判断。但是通过使用Dapper的trace信息和DAPI MapReduce接口可以自动化的确定服务间依赖关系。
帮助网络管理员对跨集群的网络活动进行应用层的分析。帮助发现某些昂贵的网络请求开销的产生原因。
很多存储系统都是共享的。比如GFS,会有很多用户,有的可能是直接访问GFS,有的可能是比如通过Bigtable产生对GFS的访问,如果没有Dapper,对这种共享式系统将会很难调试,通过Dapper提供的数据,共享服务的owner可以方便的对用户根据各项指标(比如网络负载,请求耗时)进行排序。
救火。但是不是所有的救火,都可以使用Dapper来完成。比如,那些正在救火的Dapper用户需要访问最新的数据,但是他可能根本没有时间写一个新的DAPI代码或者等待周期性报告的产生。对于那些正在经历高延迟的服务,Dapper的用户接口并不适于用来快速定位延迟瓶颈。但是可以直接与Dapper daemon进行交互,通过它可以很容易地收集最新数据。在发生灾难性的故障时,通常没有必要去看统计结果,单个例子就可以说明问题。但是对于那些共享存储服务来说,信息聚合会很重要。对于共享服务来说,Dapper的聚合信息可以用来做事后分析。但是如果这些信息的聚合无法在问题爆发后的10分钟之内完成,那么它的作用将会大大削弱,因此对于共享服务来说,Dapper在救火时的效果没有想象中的那么好。
通过开放跟踪数据给用户,激发了用户创造力,产生了很多意料之外的应用。那些没有跟踪功能的应用只需要用新的库重新编译下它们的程序,就获得了跟踪功能,迁移非常方便。
但是还存在如下一些需要改进的地方:
合并产生的影响。我们通常假设各种子系统会一次处理一个请求。但是某些情况下,请求会被缓存,然后一次性地在一组请求上执行某个操作(比如磁盘写入)。在这种情况下,被追踪的请求拿到的实际上并不是它本身的处理过程。
对批量处理进行跟踪。虽然Dapper是为在线服务系统而设计,最初是为了理解用户发送请求给Google后产生的一系列系统行为。但是离线的数据处理实际上也有这样的需求。在这种情况下,我们可以将trace id与某些有意义的工作单元进行关联,比如输入数据里的一个key(或者是一个key range)。
寻找根本原因。Dapper可以迅速找到系统短板,但是在寻找根本原因时并不那么高效。比如某个请求变慢可能并不是因为它自己的原因,而是因为在它之前已经有很多请求在排队。用户可以在应用层将某些参数,比如队列大小交给跟踪系统。
记录内核级信息。我们有很多工具可以进行内核执行过程的跟踪和profiling,但是直接将内核级信息捆绑到一个应用层的trace context中很难优雅的实现。我们打算采用一种折中的解决方案,通过在应用层获取内核活动参数的快照,然后将它们与一个活动span关联起来。
- Dapper,大规模分布式系统的跟踪系统--转
原文地址:http://bigbully.github.io/Dapper-translation/ 概述 当代的互联网的服务,通常都是用复杂的.大规模分布式集群来实现的.互联网应用构建在不同的软件模 ...
- Dapper,大规模分布式系统的跟踪系统
概述 当代的互联网的服务,通常都是用复杂的.大规模分布式集群来实现的.互联网应用构建在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发.可能使用不同的编程语言来实现.有可能布在了几千台服务器 ...
- Pinpoint是一个开源的 APM (Application Performance Management/应用性能管理)工具,用于基于java的大规模分布式系统,基于Google Dapper论文
Pinpoint是一个开源的 APM (Application Performance Management/应用性能管理)工具,用于基于java的大规模分布式系统,基于Google Dapper论文 ...
- 专訪阿里陶辉:大规模分布式系统、高性能server设计经验分享
http://www.csdn.net/article/2014-06-27/2820432 摘要:先后就职于在国内知名的互联网公司,眼下在阿里云弹性计算部门做架构设计与核心模块代码的编写,主要负责云 ...
- Google在情报搜集中的基础技巧
Google在情报搜集中的基础技巧 作者:王宇阳 时间:2019-06-06 作者笔记 Google Hacking 是指使用特定的高级的google搜索语法,收集渗透测试目标的信息,查找目标的配 ...
- 译:Google的大规模集群管理工具Borg(一)------ 用户视角的Borg特性
概述 Google的Borg系统是一个集群管理工具,在它上面运行着成千上万的job,这些job来自许许多多不同的应用,并且跨越多个集群,而每个集群又由大量的机器构成. Borg通过组合准入控制,高效的 ...
- 浅析HBase:为高效的可扩展大规模分布式系统而生
什么是HBase Apache HBase是运行在Hadoop集群上的数据库.为了实现更好的可扩展性(scalability),HBase放松了对ACID(数据库的原子性,一致性,隔离性和持久性)的要 ...
- 《Google软件测试之道》基础
<Google软件测试之道>,一直听朋友讲起这本书,出于琐事太多,一直没机会拜读,最近部门架构觉得我们IT部门的技术太low,就给我们挑选了一些书籍,让我们多看看... 个人的一种学习习惯 ...
- 译:Google的大规模集群管理工具Borg(二)------ Borg架构
3.Borg 架构 一个Borg的cell由一系列的机器组成,通常在cell运行着一个逻辑的中央控制器叫做Borgmaster,在cell中的每台机器上则运行着一个叫Borglet的代理进程.而Bor ...
随机推荐
- 字符串strcpy
strcpy函数的表达方式: //把一个char组成的字符串循环右移n个,如:“abcdefghi",n=2,移动后"hiabcdefgh" #include <i ...
- 服务器列表里找不到OracleOraDb10g_home1TNSListener
先安装的ORACLE DB,后配置的数据库,TNSNAMES.ORA, LISTENER.ORA配置完毕,客户端连接不上TNS服务器,发现服务列表里没有OracleOraDb10g_home1TNSL ...
- css添加样式的四种方式
1. 导入样式:在 .css文件中使用@import url("...")来引入另一个css样式表 2. 外部样式:在html页面中的head中使用 link 标签引入,如< ...
- BFC?来自CSS中的BFC
浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为“visiable”的块级盒子 ...
- XML代码生成器——XMLFACTORY 简介(二)
XML代码生成器——XMLFACTORY 简介(二) 因为春节和项目上线的原因,离写上一篇文章的时间已经好久了. 不知道是事情太多了,还是自已效率太低了.总之是时间不够用. 哎,苦逼的程序员 ...
- 远程通知中app更新提示。
// // AppDelegate.m // SDJK // // Created by Jobs on 6/13/16. // Copyright (c) 2016 com.FlintInfo.dE ...
- 页面上常用的一些小功能--QQ、回到顶部
1.QQ <script charset="utf-8" type="text/javascript" src="http://wpa.b.qq ...
- css性能优化
1.前端 1.1.减少http请求次数: 1.1.1先了解下HTTP对性能的影响,HTTP是浏览器和服务器通过Interet进行相互通信的协议.HTTP是一种客服端/服务器协议,有请求和响应构成. 浏 ...
- Installscript如何给自定义路径的变量赋值
installscript自定义路径的赋值 TextSub("MY_WINDOWS_TEMP_SQL2008_DIR")="C:\\Windows\\temp2\\&q ...
- OpenStack虚拟机DHCP获取不到IP地址排查
版本:OpenStack Liberty Neutron DVR 现象: 1.在虚拟机内部不停地dhclient 2.在虚拟机所属的计算节点的物理网卡上抓包,发现该虚拟机发出的dhcp广播包 3.在虚 ...