分布式调用跟踪与监控实战

来源:云栖社区

更多深度文章,请关注云计算频道:https://yq.aliyun.com/cloud

分布式调用系统的现状

当前,随着互联网架构的扩张,分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络。

分布式调用跟踪与监控实战

如上图右侧所示,当应用A发出某个请求时,其背后可能有数十个甚至更多的服务被调用,可谓是“牵一发而动全身”。

如果将分布式系统比作高速公路网,每个前端的请求就相当于高速上行驶的车辆,而处理请求的应用就是高速上的收费站,在收费站上将车辆通行信息记录成日志,包括时间、车牌、站点、公路、价格等,如果将所有收费站上的日志整合在一起,便可以通过唯一的车牌号确定该车的完整通行记录;分布式调用系统跟踪和监控就是类比这种思想,对每一次请求进行跟踪,进而明确每个请求所经过的应用、耗时等信息。

阿里巴巴的分布式调用跟踪实现——鹰眼

分布式调用跟踪与监控实战

阿里巴巴中分布式调用跟踪是采用鹰眼(EagleEye)系统来实现的,鹰眼是基于日志的分布式调用跟踪系统,其理念脱胎于Google Dapper论文,其关键核心在于调用链,为每个请求生成全局唯一的ID(Traceld),通过它将不同系统的“孤立的”调用信息关联在一起,还原出更多有价值的数据。

分布式调用跟踪与监控实战

上图是一条来自生成环境的调用链,在应用名列可以看到请求中间过程所经过的一系列应用,可以看到最先经过Buy应用,后续调用delivery、tee、inventoryplatform等,形成调用树(树上的缩进表示嵌套关系),从调用树上很容易看到前端请求的完整处理过程。

另外值得注意的一点,上图是由白色背景和蓝色背景组成。其中蓝色背景表示调用链经过消息之后,变成了异步的消息通道,其后续处理过程也都是异步处理过程;白色背景处表示同步过程。一般而言,对于前端的用户等待的时间是不包含蓝色背景内的耗时,也就是只包含了同步处理的时间。

在上图所示的页面中也清晰地展示了每块应用处理请求得具体耗时,非常直观地进行定位;此外,状态信息也是值得关注的一点,如上图所示,如果在调用过程中发生错误,就会出现异常(图中红色区域所标注),通过点击状态码,用户可以查看错误的具体信息。

鹰眼于2013年在阿里巴巴内部上线,目前支撑阿里集团泛电商、高德、优酷等业务,技术层面覆盖前端网关接入层、远端服务调用框架(RPC)、消息队列、数据库、分布式缓存、自定义组件(如支付、搜索SDK、本地方法埋点等);2016年在阿里云的中间件云产品EDAS发布,对外提供服务;此外,鹰眼也支持私有云输出。

使用场景

下面来具体看一下调用链的具体使用场景。

定位异常、耗时问题

分布式调用跟踪与监控实战

可以在业务异常日志的错误信息中找到Traceld(如图中的TraceId=ac18287913742691251746923),之后在鹰眼系统中只需要输入Traceld,就可以看到调用链中具体的情况,在调用链上更加直观地定位到问题(如上图所示),层层排查后确定问题的所在。

带调用链下钻的监控报表

分布式调用跟踪与监控实战

对于分布式调用跟踪系统而言,它并不仅仅提供了调用链这一功能,因为它对所有中间件的调用做埋点,所以中间件上的所有情况都可以监控的到。因此,在形成调用链的过程中也会形成一份详细的调用监控报表,它与其他监控的不同之处在于:该监控报表是带有上下钻取功能的报表。因为调用链是详细的底层统计,对上可以形成的报表维度是非常丰富的,在上图所示的调用报表里,不仅可以看到服务的情况,还可以下钻到它所调用服务的情况;另外从监控报表上还可以进行调用链的下钻,查看清晰的调用链信息。

链路分析

链路与调用链不同,链路是一个统计学的概念,而调用链是单体调用的过程。分析链路的价值主要体现在以下几点:

(1)拓扑形态分析:分析来源、去向,识别不合理来源;

(2)依赖树立:识别易故障点/性能瓶颈、强依赖等问题;

(3)容量估算:根据链路调用比例、峰值QPS评估容量;

(4)异常个体识别:寻找集群中与其他个体有差异的实例。

下面来具体分析这四点。

拓扑形态分析:分析来源、去向,识别不合理来源

分布式调用跟踪与监控实战

上图是全局调用拓扑图,可以明显的看到不同的应用之间存在复杂的调用关系,也可以查看某个应用和其他应用之间的调用关系以及调用的频次;图中红点表示在调用过程中出现错误。

通过该拓扑图,架构师可以清楚地观察到系统上的调用情况,此外,点击全局调用拓扑图上的某个节点,可以下钻到下图所示的单应用链路拓扑图。

分布式调用跟踪与监控实战

在以某应用为中心的单应用链路拓扑图,可以查看该应用在调用链上下游的应用之间的具体调用关系。

依赖梳理和容量估算

链路分析除了进行拓扑形态分析之外,还能进行依赖梳理:识别易故障点、性能瓶颈、强依赖等问题;也可以根据链路调用比例、峰值QPS 评估容量。

分布式调用跟踪与监控实战

上图是一份单链路报表,单链路报表是指同一HTTP入口的调用链叠加形成、包含所有依赖情况的调用关系。上图左侧模糊部分是一棵调用树,它表现了应用之间的依赖关系,与调用链不同的是,这种依赖关系是统计学意义上的依赖,因此在该报表上包含了QPS和统计QPS统计类型的数据。在进行容量预估时,可以很容易分析上游应用对下游造成的压力。

在该报表上,还可以进行依赖梳理方面的工作,根据出错率确定易故障点;此外,那些存在强依赖、错误阻塞的地方都是潜在故障点;最后,还可以根据耗时比例进行相关的性能优化。

异常个体识别:寻找集群中与其他个体有差异的实例

异常个体识别是链路分析的另一大作用,可以很容易地识别集群中与其他个体存在差异的实例。

分布式调用跟踪与监控实战

在集群中,由于网络或机器配置等原因导致不同的计算机处理能力有差别,因此可能存在某些机器空闲而其他机器繁忙的现象,正如上图的热点图显示,集群中会存在负载不均匀的情况,通过调用链可以非常容易地识别集群中存在问题的机器;此外,还可以通过离散点、波形图等方式发现异常的个体。

分析出异常个体只是链路分析的第一步,分析出异常个体之后,能够自动提醒用户或者是自动处理异常情况才是后续的关键问题,而不是人工去检查每个报表中是否存在异常。

实现原理

在分析调链实现的原理之前,首先需要明确几个关键概念:

(1)全局唯一ID:Traceld。Traceid是与每次请求相对应,保证全局唯一;用于将调用链的各个调用重新关联起来。Traceld的实现有以下三种方案:

方案一:由中心节点统一分配。

方案二:在本地直接生成,无业务语言(UUID)。

方案三:在本地直接生成,但是附带业务语义。

方案一对中心节点过于依赖,存在性能问题;方案二不包含业务语言。因此,综合方案一、二,我们最后选择了方案三。

分布式调用跟踪与监控实战

图中给出了目前使用的Traceid的组成部分,包括IPv4、毫秒时间、顺序数、标志位、进程PID五部分。

(2)调用链内部的唯一ID:RpcId(也叫SpanId)。它用于还原调用顺序和调用间的嵌套关系,需要考虑的调用关系包括同步、并发、异步、一对多。那么用什么方式实现RpcId 适合表示上述关系呢?

分布式调用跟踪与监控实战

阿里内部实现RpcId的方案(方案二)是多级序号的方案:生成一个RpcId的同时,也会包含所有上级的RpcId,具体示意图如上图所示。从上图可以形象地看到RpcId的概念,例如从0.3.1.1,可以得知它上一级序号为0.3.1,再由0.3.1得知其上一级序号为0.3,以及上上一级序号0;此外,多级序号的实现方式相对于单级序号方式在成本方面也得到降低。

另外,在整个调用链里还涉及其他一些关键概念:

(1)调用相关属性Tags:它记录仅和本次调用相关的信息,是一个K-V 集合。常见的Tags一般包括调用时间、调用耗时、调用类型、服务名、操作名、响应状态码、对端服务器地址等信息。

(2)调用透传信息UserData(也叫Baggage):它记录同一条调用链上下游共享的信息,也是一个K-V 集合。常见的UserData包括通用数据、特殊指令、调用路由控制,影响部分中间件的路由走向。

(3)调用上下文RpcContext(也叫SpanContext):它由TraceId、RpcId、Tags、UserData 共同组成,在进程内部时,上下文保存于ThreadLocal,对业务透明;在网络通讯时,上下文会和实际内容一起被传输到对端。

整体架构

下面来看一下分布式调用跟踪的整体架构。

分布式调用跟踪与监控实战

如上图所示,在架构的最上端是应用集群,每台机器中都有一个带鹰眼埋点的中间件,该中间件负责向日志文件中写入数据,每台机器上的数据收集agent从日志文件读取数据,实现实时收集日志;在鹰眼系统中通过实时处理集群对实时日志进行计算分析,得到两种类型的数据,分别是统计类型的报表(存放在HBase中)和调用链调用明细详情(存放在HiStore中);另外,涉及到离线数据分析的数据使用ODPS离线分析集群进行计算,主要是一些模型建设方面的分析。

架构中最下侧室鹰眼控制台,通过控制台可以查看实时处理集群后的结果;此外,控制台还负责实时处理集群和埋点相关的配置推送。

整体处理流程

数据整体处理流程抽象为埋点、采集、分析、存储四部分,下面来具体分下每个部分。

埋点客户端

埋点客户端首先需要注意减少对业务线程的影响,降低资源消耗;其次由于每个网络请求至少1次调用记录,QPS越高则数据产生越快,进而导致成本很难控制;另外,业务方是希望埋点对业务是无侵入的,部署在任何位置均可,进而导致运维环境相对复杂。

分布式调用跟踪与监控实战

为了解决上述挑战,在阿里内部我们选用了完全自行实现的基于日志的输出方案,在提升输出性能方面:采用异步无锁队列写日志(定制的Disruptor);减少输出内容,长字符串编码;日志输出缓存,限制IO次数,每秒刷新;高效多进程并发写文件。

在运维层面,也进行了很多优化:日志文件按大小滚动,自动清理;统一字符编码,统一时区;全局配置推送管控;异常状态自动降级。

因为对业务是无侵入埋点,所以在内部中间件直接进行埋点植入;对于非内部中间件,如开源组件,第一种方式是提供了埋点的组件包或通过扩展的方式增加埋点;第二种方法是使用AOP一类技术,在运行期对目标埋点位置做字节码增强;第三种方式是适配已有的链路埋点,如OpenTraceing或Zipkin等。

调用链采样

因为QPS越高,需要生成的调用日志也就越高。因此,为了降低整体的输出数据量,引入例如采样的概念,根据TraceId中的顺序数进行采样,提供了多种采样策略搭配:

• 100% 采样:它会对业务带来影响,因此最好内置支持客户端自动降级;

• 固定阈值采样:全局或租户内统一控制;

• 限速采样:在入口处按固定频率采样若干条调用链;

• 异常优先采样:调用出错时优先采样;

• 个性化采样:按用户ID、入口IP、应用、调用链入口、业务标识等配置开启采样。

通过上面这五种采样策略的搭配使用,可以灵活地控制调用链上数据的输出,确保数据量不会过大。

数据采集

分布式调用跟踪与监控实战

在数据采集方面主要面临内部和云上两个挑战:

•内部:在阿里内部,其实是一个比较可控的环境,但是因为数据量太大,每日百TB级别的规模,面临着节约成本的问题;

•云上:尽管数据量相对较小,由于网络环境比较复杂以及各种限制,数据采集依旧困难。

针对内部的挑战,我们的解决方案是在埋点时输出日志到本地,通过日志Agent读取日志,然后再通过实时计算的处理层主动拉取日志再进行处理。该方案直接复用应用机器存储日志,并且采用拉模式防止流量冲击过大。

针对云上的挑战,我们的解决方案利用消息队列的方式,埋点层主动发送消息,消息队列对消息进行存储,数据处理层从消息队列上订阅消息。这种方案可做到数据不丢,且主动推送可以提高实时性,环境适应性强;但这种解决方案的成本是比较高的。

数据分析

分布式调用跟踪与监控实战

数据采集的下一阶段是数据分析。数据分析主要分为调用级分析和链路级分析:

•调用级分析是指对单次调用数据,可以马上进行分析,按照指定的统计维度进行实时聚合即可,实时性为秒级。对于上文提到的采样情况下,为了保证数据统计的准确性,埋点层需要另外输出一份统计日志。

•链路级分析是调用链中最为关键的分析,它一般采用离线计算方案,将统一个TraceId的调用链先汇总在同一个Reduce任务重,调用链重组后再进行分析。类似于强弱依赖分析、调用频繁度分析、耗时瓶颈分析都是属于链路级分析。链路级分析的难点在于数据残缺补全,维度归一化和统计维度爆炸等问题。

数据存储

分布式调用跟踪与监控实战

在数据存储时,不同的数据类型存储的方式存在差异:

对于时间序列数据,我们是基于HBase存储,是OpenTSDB的修改后方案,解决聚合数据重复提交以及统计维度爆炸等问题。

对于调用链数据存储,分为三个阶段:

(1)阶段一:使用HBase存储,TraceId做rowkey;

(2)阶段二:使用Hadoop/ODPS 存储,按TraceId 的时间戳和哈希值进行分片,分片内按TraceId 排序;针对调用中记录的每个列进行针对性压缩,节省存储;

(3)阶段三:使用分库分表的HiStore 存储(将在DRDS 铂金版推出), 按TraceId 的时间戳和哈希值进行分库分表;HiStore 支持列式高压缩比存储,兼容MySQL 生态,非常适合写多读少的场景。

最佳实践

调用链作为排查问题的核心,通过其可以将各类数据关联在一起,提高问题排查能力。下面来看一下调用链的最佳实践——全息排查。

全息排查

分布式调用跟踪与监控实战

在实际问题排查中经常会遇到上图所示的问题,这些问题都具有明确的业务含义,这些问题尽管看上去和调用链并无关系,但可以用调用链得到很好的解决。如上图右侧所示,A-E五个节点在调用链上承载的调用关系实际上都是一些具体的业务,例如节点A处理HTTP请求表示卖家abc点击下单;在调用B时其实在计算卖家xyz在该路线的运费等等。在排查问题时,最有价值的切入点在于先从业务问题出发,再进一步在调用链中确认问题所在之处。

分布式调用跟踪与监控实战

分布式调用跟踪与监控实战

我们可以根据业务时间ID反查调用链,从而顺藤摸瓜找到更多的上下游业务信息。例如一个交易订单(2135897412389123)发现存在问题,我们可以根据订单号查到与之绑定的TraceId,根据TraceId不仅可以查看系统调用的事件,还可以看到与业务相关的事件,如用户下单、当前库存情况等,也就是说根据交易ID可以在调用链上查看交易、商品库存以及支付等信息,大大提升错误排查速度。

分布式调用跟踪与监控实战

回到刚才提到的三个问题:要分析由哪笔订单操作引起的调用异常其实是TraceId到OrderId的一次关联;要分析异常订单是否由卖家对所在商品的运费模板的某些异常操作导致其实是根据OrderId关联ItemId再关联TemplateId,最后关联到TraceId;对于第三个问题,通常是由UserId关联到TraceId再关联到MyBizld。

根据这些问题及其解决方案可以看到,全息排查的关键在于:业务时间id与TraceId/RpcId的双向绑定。

常见的双向绑定有三种实现方式:

(1)在调用链的Tags 或UserData 中放入业务事件id,从而建立调用链到业务事件id 的关联;

(2)打通TraceId 到数据库的数据变更的关联,从而建立调用链到每次数据变更的关联;

(3)在业务日志中记录TraceId、业务事件id 等信息,从而建立调用链与业务事件日志的关联。

目前,基于阿里云ARMS集成了上述三种双向绑定实现方式,用户可以在产品上轻松配置搞定。

全息排查全景图

分布式调用跟踪与监控实战

上图是阿里巴巴内部的全息排查全景图。该图的核心部分是鹰眼最初覆盖的的后端系统,包括服务、消息和缓存;在前端层面涉及前端用户访问日志,具有关联TraceId的能力;在移动端也具有关联TraceId的能力;通过对TraceId进行关联,可以打通用户访问日志;在数据库层面,通过SQL语句将TraceId传到数据库的binlog中,在数据复制和数据分发时可以非常容易获取到每次数据变更的记录与TraceId的关联;另外,业务通过自身的业务日志和异常堆栈也可以打印TraceId;这样一来,业务层、移动端、前端、数据层所有的组件都与TraceId进行了关联,再关联上业务中的订单号、用户号、商品号、物流单号、交易单号,最后形成一个非常强大的生态——从一个调用链可以看到上下游相关的订单、用户的详细信息,同时可以根据订单查到与该订单相关的业务ID,再根据业务ID扩展到与其相关的更多ID,甚至是TraceId,最后形成TraceId-->业务ID-->新的TraceId的网状结构,将排查问题转化为从网状结构中寻找需要的整段信息。

通过EDAS+ARMS打造的立体化监控体系

目前,通过阿里云提供的EDAS结合ARMS可以打造立体化监控体系,其中EDAS用于应用管控层面,用于控制链路和应用;而ARMS更关注业务运营层面,如电商交易、车联网、零售;实际上,监控需要全方位关注业务、链路、应用、系统,通过ARMS与EDAS相互补全,形成了立体化监控体系。

来源:http://www.toutiao.com/i6416126902448161281/?tt_from=weixin_moments&utm_campaign=client_share&from=timeline&app=news_article&utm_source=weixin_moments&iid=8900078166&utm_medium=toutiao_android&wxshare_count=2&pbid=1493950691

分布式调用跟踪系统的设计和应用

>>为什么需要分布式调用跟踪系统

随着分布式服务架构的流行,特别是微服务等设计理念在系统中的应用,业务的调用链越来越复杂,

可以看到,随着服务的拆分,系统的模块变得越来越多,不同的模块可能由不同的团队维护,

一个请求可能会涉及到几十个服务的协同处理, 牵扯到多个团队的业务系统,那么如何快速准确的定位到线上故障?
同时,缺乏一个自上而下全局的调用id,如何有效的进行相关的数据分析工作?

对于大型网站系统,如淘宝、京东等电商网站,这些问题尤其突出。

一个典型的分布式系统请求调用过程:

比较成熟的解决方案是通过调用链的方式,把一次请求调用过程完整的串联起来,这样就实现了对请求调用路径的监控。

>>调用跟踪系统的业务场景

(1)故障快速定位

通过调用链跟踪,一次请求的逻辑轨迹可以用完整清晰的展示出来。
开发中可以在业务日志中添加调用链ID,可以通过调用链结合业务日志快速定位错误信息。

(2)各个调用环节的性能分析

在调用链的各个环节分别添加调用时延,可以分析系统的性能瓶颈,进行针对性的优化。

(3)各个调用环节的可用性,持久层依赖等

通过分析各个环节的平均时延,QPS等信息,可以找到系统的薄弱环节,对一些模块做调整,如数据冗余等。

(4)数据分析等

调用链是一条完整的业务日志,可以得到用户的行为路径,汇总分析应用在很多业务场景。

>>分布式调用跟踪系统的设计

(1)分布式调用跟踪系统的设计目标

低侵入性,应用透明:

作为非业务组件,应当尽可能少侵入或者无侵入其他业务系统,对于使用方透明,减少开发人员的负担

低损耗:

服务调用埋点本身会带来性能损耗,这就需要调用跟踪的低损耗,
实际中还会通过配置采样率的方式,选择一部分请求去分析请求路径

大范围部署,扩展性:

作为分布式系统的组件之一,一个优秀的调用跟踪系统必须支持分布式部署,具备良好的可扩展性

(2)埋点和生成日志

埋点即系统在当前节点的上下文信息,可以分为客户端埋点、服务端埋点,以及客户端和服务端双向型埋点。

埋点日志通常要包含以下内容:

TraceId、RPCId、调用的开始时间,调用类型,协议类型,调用方ip和端口,请求的服务名等信息;
调用耗时,调用结果,异常信息,消息报文等;
预留可扩展字段,为下一步扩展做准备;

(3)抓取和存储日志

日志的采集和存储有许多开源的工具可以选择,
一般来说,会使用离线+实时的方式去存储日志,主要是分布式日志采集的方式。
典型的解决方案如Flume结合Kafka等MQ。

(4)分析和统计调用链数据

一条调用链的日志散落在调用经过的各个服务器上,
首先需要按 TraceId 汇总日志,然后按照RpcId 对调用链进行顺序整理。
调用链数据不要求百分之百准确,可以允许中间的部分日志丢失。

(5)计算和展示

汇总得到各个应用节点的调用链日志后,可以针对性的对各个业务线进行分析。
需要对具体日志进行整理,进一步储存在HBase或者关系型数据库中,可以进行可视化的查询。

>>调用跟踪系统的选型

大的互联网公司都有自己的分布式跟踪系统,
比如Google的Dapper,Twitter的zipkin,淘宝的鹰眼,新浪的Watchman,京东的Hydra等。

(1)Google的Drapper

Dapper是Google生产环境下的分布式跟踪系统,Dapper有三个设计目标:

低消耗:跟踪系统对在线服务的影响应该做到足够小。

应用级的透明:对于应用的程序员来说,是不需要知道有跟踪系统这回事的。如果一个跟踪系统想生效,就必须需要依赖应用的开发者主动配合,那么这个跟踪系统显然是侵入性太强的。

延展性:Google至少在未来几年的服务和集群的规模,监控系统都应该能完全把控住。

Drapper的日志格式:

dapper用span来表示一个服务调用开始和结束的时间,也就是时间区间。

dapper记录了span的名称以及每个span的ID和父ID,如果一个span没有父ID被称之为root span。所有的span都挂在一个特定的trace上,共用一个traceID,这些ID用全局64位整数标示。

Drapper如何进行跟踪收集:

分为3个阶段:

①各个服务将span数据写到本机日志上;

②dapper守护进程进行拉取,将数据读到dapper收集器里;

③dapper收集器将结果写到bigtable中,一次跟踪被记录为一行。

 

(2)淘宝的鹰眼

关于淘宝的鹰眼系统,主要资料来自于内部分享,

鹰眼埋点和生成日志:

如何抓取和存储日志:

鹰眼的实现小结:

来源:http://www.cnblogs.com/Leo_wl/p/5721754.html

 

-----------------------------

微服务架构下,如何实现分布式跟踪?

 

前段时间,我们有发布过一篇题为《类似Google Dapper,微服务需要这样的分布式跟踪工具》的文章,很多读者反馈没看尽兴,确实,文章只是谈到分布式追踪工具的意义,以及可以解决什么问题,但并没有谈到如何实现分布式追踪。今天这篇文章,作者是东软集团基础软件事业部技术总监,他在这方面有丰富的经验,文中他将会聊到目前主流的几个解决方案实现思路以及他们的落地方案。

另外,这里有个不错的关于spring Boot和Spring Cloud的沙龙活动,免费,在北京,感兴趣的同学别忘了报名。

随着互联网技术的高速发展,各种创新技术、前沿概念如雨后春笋般层出不穷,云服务、云计算、大数据处理、大数据分析……,以往单应用的服务架构已经很难处理如山洪般增长的信息数据,随着分布式的普及、服务的快速增长与云计算技术的进步,微服务架构逐渐进入人们的实现,它也因其特有的优势而备受关注。

微服务架构的本质,是把整体的业务拆分成很多有特定明确功能的服务,通过很多分散的小服务之间的配合,去解决更大,更复杂的问题。对被拆分后的服务进行分类和管理,彼此之间使用统一的接口来进行交互。

微服务的特点决定了功能模块的部署是分布式的,以往在单应用环境下,所有的业务都在同一个服务器上,如果服务器出现错误和异常,我们只要盯住一个点,就可以快速定位和处理问题,但是在微服务的架构下,大部分功能模块都是单独部署运行的,彼此通过总线交互,都是无状态的服务,这种架构下,前后台的业务流会经过很多个微服务的处理和传递,我们难免会遇到这样的问题:

  • 分散在各个服务器上的日志怎么处理?
  • 如果业务流出现了错误和异常,如何定位是哪个点出的问题?
  • 如何快速定位问题?
  • 如何跟踪业务流的处理顺序和结果?

我们发现,以前在单应用下的日志监控很简单,在微服务架构下却成为了一个大问题,如果无法跟踪业务流,无法定位问题,我们将耗费大量的时间来查找和定位问题,在复杂的微服务交互关系中,我们就会非常被动。

对于这个问题,业内已经有了一些实践和解决方案,让我们来看看行业内的领先设计思想。

Google Dapper

Google公司广泛使用了分布式集群,为了应对自身大规模的复杂集群环境,Google公司研发了Dapper分布式跟踪系统,并发表了论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,给行业内分布式跟踪的实现提供了非常有价值的参考,该论文也成为了当前分布式跟踪系统的理论基础。

我们先来看个例子:

图1 这个路径由用户的X请求发起,穿过一个简单的服务系统。用字母标识的节点代表分布式系统中的不同处理过程。

分布式服务的跟踪系统需要记录在一次特定的请求中系统中完成的所有工作的信息。举个例子,上图展现的是一个与5台服务器相关的一个服务,包括:前端(A),两个中间层(B和C),以及两个后端(D和E)。当一个用户(这个用例的发起人)发起一个请求时,首先到达前端,然后发送两个RPC调用到服务器B和C。B会马上做出反应,但是C需要和后端的D和E交互之后再返还给A,由A来响应最初的请求。对于这样一个请求,简单实用的分布式跟踪的实现,就是为服务器上每一次发送和接收动作来收集跟踪标识符(message identifiers)和时间戳(timestamped events)。

基于这个模型,Google在此论文中提出了几个重要的概念:

1、基于标注(annotation-based),又叫植入点或埋点

在应用程序或中间件中明确定义一个全局的标注(annotation),它可以是一个特殊的ID,通过这个ID连接每一条记录和发起者的请求,当然,这需要代码植入,在生产环境中,因为所有的应用程序都使用相同的线程模型,控制流和RPC系统,可以把代码植入限制在一个很小的通用组件库中,从而达到监测系统应用对开发人员的透明。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中,这是一个重要的植入点。

2、跟踪树和span

图2:5个span在Dapper跟踪树中的关联关系

在Dapper跟踪树结构中,树节点是整个架构的基本单元,而每一个节点又是对span的引用。节点之间的连线表示的span和它的父span的直接关系。通过简单的parentId和spanId就可以有序地把所有的关系串联起来,达到记录业务流的作用。

Twitter公司的Zipkin

Twitter公司的Zipkin是Google Dapper系统的开源实现,Zipkin严格按照Dapper论文实现,采用Scala编写,并且紧密集成到Twitter公司自己的分布式服务Finagle中,使得跟踪做到对应用透明。

图3:Zipkin应用架构图

Zipkin的整体架构如上图所示,涵盖了信息的收集、处理和展现。

淘宝鹰眼系统(EagleEye)

淘宝鹰眼是基于网络调用日志的分布式跟踪系统,它可以分析网络请求在各个分布式系统之间的调用情况,从而得到处理请求的调用链上的入口URL、应用服务的调用关系,从而找到请求处理瓶颈,定位错误异常的根源位置。同时,业务方也可以在调用链上添加自己的业务埋点日志,使各个系统的网络调用与实际业务内容得到关联。

图4:鹰眼系统的总体架构图

我们的解决方案

针对于微服务,东软平台产品提供了一套完整的微服务解决方案,在此基础上,对微服务架构进行了扩展,基于Google Dapper的概念,设计了一套基于微服务架构的分布式跟踪系统。

该跟踪系统支持基于dubbo的微服务框架的监控,以及分布式服务调用链跟踪:

图5:东软UniEAP平台基于微服务的分布式跟踪系统流程设计图

分布式跟踪系统的整体流程是通过扩展dubbo作为入口,把监控代码植入到dubbo-filter扩展模块中,然后通过trace-client模块抓取日志数据,存入文件服务器,为了避免产生大量Trace对象造成内存堆积引发的GC问题,trace首先采取写入堆外内存的方式落地,然后通过trace-agent代理模块读取日志信息,给trace-collector收集模块提供日志数据,trace-collector收集模块通过提供统一的接口,为外部获取数据提供支持,可以传输到数据库记录,或者传输给其他的数据分析产品。Trace-web模块作为可视化展示平台,展现服务的完整跟踪链条、心跳监控信息、dubbo原生监控信息,达到数据的展示工作。

除了数据的跟踪以外,该系统还会整合数据分析功能:

图6:集成数据分析功能,提升数据的利用价值

通过集成可视化分析产品,简单的分布式跟踪功能变成了可视化的监控系统,跟踪中产生的数据,会发挥出更大的价值:

  1. 实时抓取数据,实时分析统计,生成统计和报表
  2. 可视化的报表系统,更快的了解系统运行状态
  3. 搜索功能,快速的定位关键问题
  4. 数据挖据,利用优秀的数据分析能力和数据模型,进行数据预测
  5. 分布式跟踪系统应用展望

在分布式场景越来越普及的今天,分布式跟踪将作为微服务必备的基础组件存在,完善的跟踪系统可以极大的提高开发和运维的效率,是企业应用发展不可获缺的组成部分,特别是以下几点:

1、业务流调用流程跟踪

分布式系统的所有日志信息可以通过完善的跟踪串联起来,使系统的运维更加稳定,定位问题更加准确。

2、可视化的监控界面

通过分布式跟踪系统的可视化监控页面,避免了去服务器上查看日志的烦恼。

3、业务分析

在使用了分布式跟踪系统后,我们可以快速的梳理每个调用链路,分析耗时过长的业务是如何产生的,并且可以定位性能不佳的调用片段,合理的分析问题,为性能优化提供非常有价值的参考意见。

发表评论