随着互联网架构的扩张,分布式系统变得日趋复杂,愈来愈多的组件开始走向分布式化,如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络,那如今的问题是一个请求通过了这些服务后其中出现了一个调用失败的问题,只知道有异常,但具体的异常在哪一个服务引发的就须要进入每个服务里面看日志,这样的处理效率是很是低的。java
分布式调用链其实就是将一次分布式请求还原成调用链路。显式的在后端查看一次分布式请求的调用状况,好比各个节点上的耗时、请求具体打到了哪台机器上、每一个服务节点的请求状态等等。程序员
经过调用链跟踪,一次请求的逻辑轨迹能够用完整清晰的展现出来。开发中能够在业务日志中添加调用链ID,能够经过调用链结合业务日志快速定位错误信息。sql
(2)各个调用环节的性能分析数据库
在调用链的各个环节分别添加调用时延,能够分析系统的性能瓶颈,进行针对性的优化。经过分析各个环节的平均时延,QPS等信息,能够找到系统的薄弱环节,对一些模块作调整,如数据冗余等。后端
调用链绑定业务后查看具体每条业务数据对应的链路问题,能够获得用户的行为路径,通过了哪些服务器上的哪一个服务,汇总分析应用在不少业务场景。跨域
经过可视化分布式系统的模块和他们之间的相互联系来理解系统拓扑。点击某个节点会展现这个模块的详情,好比它当前的状态和请求数量。缓存
低侵入性,应用透明:做为非业务组件,应当尽量少侵入或者无侵入其余业务系统,对于使用方透明,减小开发人员的负担服务器
低损耗:服务调用埋点自己会带来性能损耗,这就须要调用跟踪的低损耗,实际中还会经过配置采样率的方式,选择一部分请求去分析请求路径网络
大范围部署,扩展性:做为分布式系统的组件之一,一个优秀的调用跟踪系统必须支持分布式部署,具有良好的可扩展性架构
埋点即系统在当前节点的上下文信息,能够分为客户端埋点、服务端埋点,以及客户端和服务端双向型埋点。埋点日志一般要包含如下内容:
TraceId、RPCId、调用的开始时间,调用类型,协议类型,调用方ip和端口,请求的服务名等信息;
调用耗时,调用结果,异常信息,消息报文等;
预留可扩展字段,为下一步扩展作准备;
日志的采集和存储有许多开源的工具能够选择,通常来讲,会使用离线+实时的方式去存储日志,主要是分布式日志采集的方式。典型的解决方案如Flume结合Kafka等MQ。
一条调用链的日志散落在调用通过的各个服务器上,首先须要按 TraceId 汇总日志,而后按照RpcId 对调用链进行顺序整理。用链数据不要求百分之百准确,能够容许中间的部分日志丢失。
汇总获得各个应用节点的调用链日志后,能够针对性的对各个业务线进行分析。须要对具体日志进行整理,进一步储存在HBase或者关系型数据库中,能够进行可视化的查询。
一次典型的分布式调用过程,以下图所示:
Trace调用模型,主要有如下概念:
Trace:一次完整的分布式调用跟踪链路。
Span: 追踪服务调基本结构,表示跨服务的一次调用; 多span造成树形结构,组合成一次Trace追踪记录。
Annotation:在span中的标注点,记录整个span时间段内发生的事件。
BinaryAnnotation:能够认为是特殊的Annotation,用户自定义事件。
Annotation类型:保留类型
Cs CLIENT_SEND,客户端发起请求
Cr CLIENT_RECIEVE,客户端收到响应
Sr SERVER_RECIEVE,服务端收到请求
Ss SERVER_SEND,服务端发送结果
用户自定义类型:
Event 记录普通事件
Exception 记录异常事件
Client && Server:对于跨服务的一次调用,请求发起方为client,服务提供方为server
各术语在一次分布式调用中,关系以下图所示:
大的互联网公司都有本身的分布式跟踪系统,好比Google的Dapper,Twitter的zipkin,淘宝的鹰眼,新浪的Watchman,京东的Hydra等,下面来简单分析。
Dapper是Google生产环境下的分布式跟踪系统,Dapper有三个设计目标:
低消耗:跟踪系统对在线服务的影响应该作到足够小。
应用级的透明:对于应用的程序员来讲,是不须要知道有跟踪系统这回事的。若是一个跟踪系统想生效,就必须须要依赖应用的开发者主动配合,那么这个跟踪系统显然是侵入性太强的。
延展性:Google至少在将来几年的服务和集群的规模,监控系统都应该能彻底把控住。
处理分为3个阶段:
①各个服务将span数据写到本机日志上;
②dapper守护进程进行拉取,将数据读到dapper收集器里;
③dapper收集器将结果写到bigtable中,一次跟踪被记录为一行。
关于淘宝的鹰眼系统,主要资料来自于内部分享:
鹰眼埋点和生成日志:
如何抓取和存储日志,记录本地文件,使用额外的后台进程按期(时间间隔小)收集日志。这种方式的优点在于对应用的性能影响小,方便作消息堆积;可是须要在每台业务server上都部署并管理日志收集agent,运维量比较大。
鹰眼的实现小结:
注意Dapper与Eagle eye都不开源。
经过阿里云提供的EDAS结合ARMS能够打造立体化监控体系,其中EDAS用于应用管控层面,用于控制链路和应用;而ARMS更关注业务运营层面,如电商交易、车联网、零售;实际上,监控须要全方位关注业务、链路、应用、系统,经过ARMS与EDAS相互补全,造成了立体化监控体系。
架构简单。能够实现一个Trace系统的全部功能。架构以下图所示:
Transaction是最重要的事件消息类型,适合记录跨越系统边界的程序访问行为,好比远程调用,数据库调用,也适合执行时间较长的业务逻辑监控,记录次数与时间开销。Transaction可嵌套。
跨服务的跟踪功能与点评内部的RPC框架集成,这部分未开源。
对于方法调用、sql、url请求等粒度较小的兴趣点,须要业务人员手写代码实现。
直接向日志收集器发异步请求(有本地内存缓存),一台客户端会连向几个服务端,当一个服务端出问题,数据不会丢失。
当全部服务端都挂掉,消息会存入queue,当queue满了,就丢弃了,没有作数据存储本地等工做。
全量采样,系统繁忙的时候对性能影响较大(可能达到10%的影响)
最后一个稳定版本是2014年1月,以后已经失去维护。
与dubbo框架集成。对于服务级别的跟踪统计,现有业务能够无缝接入。对于细粒度的兴趣点,须要业务人员手动添加。架构以下:
Trace: 一次服务调用追踪链路。
Span: 追踪服务调基本结构,多span造成树形结构组合成一次Trace追踪记录。
Annotation: 在span中的标注点,记录整个span时间段内发生的事件。
BinaryAnnotation: 属于Annotation一种类型和普通Annotation区别,这键值对形式标注在span中发生的事件,和一些其余相关的信息。
与CAT相似。支持自适应采样,规则粗暴简单,对于每秒钟的请求次数进行统计,若是超过100,就按照10%的比率进行采样。
开源项目已于2013年6月中止维护。
功能、数据跟踪模型与hydra相似。Zipkin自己不开源,开源社区的是另一套scala实现,依托于finagle这个RPC框架。架构以下:
Zipkin与其余Trace系统的不一样之处在于:
Zipkin中针对 HttpClient、jax-rs二、jersey/jersey2等HTTP客户端封装了拦截器。能够在较小的代码侵入条件下实现URl请求的拦截、时间统计和日志记录等操做。
Cat是直接将日志发往消费集群;hydra是发给日志收集器,日志收集器推到消息队列;Zipkin的client将统计日志发往消息队列,日志收集器读取后落地存储;Dapper和Eagle eye是记录本地文件,后台进程按期扫描。
以上几款链路跟踪系统都各自知足了请求链路追踪的功能,但落实到咱们本身的生产环境中时,这些Trace系统存在诸多问题:Google和alibaba的Trace系统不开源,但现阶段来讲阿里是作得最好的,若是用的是阿里的服务器,可考虑直接用阿里的追踪系统以节省开发代价;
京东和点评的虽然开源,可是已经多年没有维护,项目依赖的jdk版本以及第三方框架过于陈旧等等,不适合用在生产环境中;
Twitter的OpenZipkin使用scala开发,并且其实现基于twitter内部的RPC框架finagle,第三方依赖比较多,接入和运维的成本很是高。
若是不是用阿里的服务,咱们能够借鉴这些开源实现的思想, 自行开发Trace系统。那是本身从0开始开发仍是基于开源方案二次开发? 这里面也要考虑到跨平台,如NET和java环境,尽可能减小原系统的侵入性或只须要更改少许的代码便可接入,在这里能够基于zipkin和pinpoint进行二次开发,功能可参考阿里的系统。
Pinpoint 与 Zipkin 都是基于 Google Dapper 的那篇论文,所以理论基础大体相同。Pinpoint 与 Zipkin 有明显的差别,主要体如今以下几个方面:
由于 Brave 的注入须要依赖底层框架提供相关接口,所以并不须要对框架有一个全面的了解,只须要知道能在什么地方注入,可以在注入的时候取得什么数据就能够了。就像上面的例子,咱们根本不须要知道 MySQL 的 JDBC Driver 是如何实现的也能够作到拦截 SQL 的能力。可是 Pinpoint 就否则,由于 Pinpoint 几乎能够在任何地方注入任何代码,这须要开发人员对所需注入的库的代码实现有很是深刻的了解,经过查看其 MySQL 和 Http Client 插件的实现就能够洞察这一点,固然这也从另一个层面说明 Pinpoint 的能力确实能够很是强大,并且其默认实现的不少插件已经作到了很是细粒度的拦截。
针对底层框架没有公开 API 的时候,其实 Brave 也并不彻底机关用尽,咱们能够采起 AOP 的方式,同样可以将相关拦截注入到指定的代码中,并且显然 AOP 的应用要比字节码注入简单不少。
以上这些直接关系到实现一个监控的成本,在 Pinpoint 的官方技术文档中,给出了一个参考数据。若是对一个系统集成的话,那么用于开发 Pinpoint 插件的成本是 100,将此插件集成入系统的成本是 0;但对于 Brave,插件开发的成本只有 20,而集成成本是 10。从这一点上能够看出官方给出的成本参考数据是 5:1。可是官方又强调了,若是有 10 个系统须要集成的话,那么总成本就是 10 * 10 + 20 = 120,就超出了 Pinpoint 的开发成本 100,并且须要集成的服务越多,这个差距就越大。
从短时间目标来看,Pinpoint 确实具备压倒性的优点:无需对项目代码进行任何改动就能够部署探针、追踪数据细粒化到方法调用级别、功能强大的用户界面以及几乎比较全面的 Java 框架支持。可是长远来看,学习 Pinpoint 的开发接口,以及将来为不一样的框架实现接口的成本都仍是个未知数。相反,掌握 Brave 就相对容易,并且 Zipkin 的社区更增强大,更有可能在将来开发出更多的接口。在最坏的状况下,咱们也能够本身经过 AOP 的方式添加适合于咱们本身的监控代码,而并不须要引入太多的新技术和新概念。并且在将来业务发生变化的时候,Pinpoint 官方提供的报表是否能知足要求也很差说,增长新的报表也会带来不能够预测的工做难度和工做量。
最后还要考虑日志收集(直接发送、记录到本地再上传)、日志接收(消息队列,直接进入ElasticSearch)、数据清洗(Logstach、Storm、SparkStreaming)、日志存储(Mysql、Hbase、ElasticSearch)、页面展现(自研仍是直接用第三方的)。