深入探究ZIPKIN调用链跟踪——拓扑Dependencies篇

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入探究ZIPKIN调用链跟踪——拓扑Dependencies篇相关的知识,希望对你有一定的参考价值。

参考技术A

Zipkin的拓扑服务zipkin-dependencies是作为zipkin的一个独立的离线服务,也就是说,只启动zipkin服务,是没法看到拓扑的,还需要自己离线启动zipkin-dependencues服务。

其中ES配置参数如下:

Zipkin出了支持elasticsearch存储,还有mysql,cassard,详细配置信息请看 源码Readme

1、图中线条说明

服务之间的线条,遵循以下原则:

2、主调被调次数说明

点开每一个服务,可以看到主调被调,比如我在拓扑图中点击
某个服务,可以与此服务有直接调用关系的服务有哪些,效果如下:

其中Uses by表示此服务作为被调服务,被哪些服务调用了;Uses表示此服务调用了哪些其他服务。

在上面的图中点击某个主调或被调服务,即可看到具体的调用次数,以及失败次数,效果如下:

通过拓扑图,宏观上,我们可以快速了解服务之间的调用关系,同时也可以知道哪些服务间调用有问题,且可以知道出现问题的一个量级是多少(失败数,调用总数)。

Zipkin拓扑denpendencies是基于上报的链路span数据再次构建出的描述链路拓扑的一种新的数据结构。

构建链路的第一步就是读取Span数据。Zipkin外部数据源支持三种,分别是Mysql,Cassandra,Elasticsearch,因此构建拓扑时,将从这三种数据源中读取Span数据。

读取Span数据源后,需要对其处理,计算出链路的拓扑。因为Span的数据量很大,普通程序计算处理无法完成任务,因此需要用到大数据框架。Zipkin官方选用的是Spark框架。Spark对Span数据进行处理,最后生成拓扑数据DenpendencyLink,然后持久化到存储中。

前端请求拓扑(DependencyLink)时,即按照查询条件,查询已经持久化后的DependencyLink,然后经过UI渲染,进行页面展示。

启动Zipkin-dependencies服务时,会传入几个参数,分别是时间day和存储类型storageType。Zipkin-dependencies服务是以天为单位进行建立拓扑,因此day将决定建立那一天的拓扑;而storageType将决定从什么储存中读取数据。

1、获取日期:

2、获取存储类型:

3、根据不同的存储启动不同的jOb:

不同的存储会定义不同Job类,因此有CassandraDependenciesJob,MySQLDependenciesJob,MySQLDependenciesJob,ElasticsearchDependenciesJob。 不同的Job主要区别在于读取Span的方式不同,而Spark对Span进行处理计算的方式基本都是相同的。 本文主要分析ElasticsearchJOb。

Job中主要逻辑都在run方法中,ElastichserchJob的Run方法定义如下:

主要步骤如下:
1、首先通过Spark的配置属性Conf,创建一个JavaSparkContext对象sc:

2、然后读取elasticsearch span数据源:

3、读取数据源后,就可以对Span进行处理了,首先按照TraceId 进行Group分组:

其中JSON_TRACE_ID Function定义如下:

4、Span按照TraceId Group 分组后,接着对Span进行处理, 创建出DenpendencyLink。

5、上面方法最终返回的是个Map类型,将其转化为pari类型,再对其进行一个reduceByKey操作:

6、Spark对Span的计算操作到这儿基本就完成了,最后将DependencyLink转化为Jso形式:

7、对于计算好的拓扑Links,将其持久化到Elasticsearch中:

整个过程到此完毕,其中最复杂也是最核心的逻辑就是计算出链路拓扑Denpendencylink,此步骤在Function TraceIdAndJsonToDependencyLinks(logInitializer, decoder)中。接下来详细分析TraceIdAndJsonToDependencyLinks完成的工作。

首先介绍一下DenpendencyLink数据结构。DenpendencyLink就是最终与页面交互的拓扑结构数据单元,字端有:

DenpendencyLink类定义如下:

TraceIdAndJsonToDependencyLinks类的定义如下:

其中call方法中,首先完成对同一TraceId的Span解码:

然后,通过DependencyLinker类构造出DependendyLink,首先构造一个SpanNode Tree:

然后利用深度优先遍历方法遍历整个,统计出CallCounts和errorCounts:

其中callCounts和errorCounts定义如下:

最后,再通过callCounts和errorCounts生成List<DependencyLink>:

这样,最终构建出了DependencyLink。

本文为我的调用链系列文章之一,已有文章如下:

祝大家工作顺利,天天开心!

调用链系列Zipkin搭建Spring-boot集承

、背景介绍

1、Zipkin是什么

Zipkin分布式跟踪系统;它可以帮助收集时间数据,解决在microservice架构下的延迟问题;它管理这些数据的收集和查找;Zipkin的设计是基于谷歌的Google Dapper论文。
每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序;如果想解决延迟问题,可以过滤或者排序所有的跟踪请求,并且可以查看每个跟踪请求占总跟踪时间的百分比。

2、为什么使用Zipkin

随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑;一个前端的请求可能需要多次的服务调用最后才能完成;当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题。

3、Zipkin下载和启动

官方提供了三种方式来启动,这里使用第二种方式来启动;

curl -sSL https://zipkin.io/quickstart.sh | bash -s
java -jar zipkin.jar

访问localhost:9411

技术分享图片

详细参考:https://zipkin.io/pages/quick...

二、Zipkin架构

跟踪器(Tracer)位于你的应用程序中,并记录发生的操作的时间和元数据,提供了相应的类库,对用户的使用来说是透明的,收集的跟踪数据称为Span;
将数据发送到Zipkin的仪器化应用程序中的组件称为Reporter,Reporter通过几种传输方式之一将追踪数据发送到Zipkin收集器(collector),
然后将跟踪数据进行存储(storage),由API查询存储以向UI提供数据。
架构图如下:

  技术分享图片

1.Trace

Zipkin使用Trace结构表示对一次请求的跟踪,一次请求可能由后台的若干服务负责处理,每个服务的处理是一个Span,Span之间有依赖关系,Trace就是树结构的Span集合;

2.Span

每个服务的处理跟踪是一个Span,可以理解为一个基本的工作单元,包含了一些描述信息:id,parentId,name,timestamp,duration,annotations等,例如:

{
      "traceId": "bd7a977555f6b982",
      "name": "get-traces",
      "id": "ebf33e1a81dc6f71",
      "parentId": "bd7a977555f6b982",
      "timestamp": 1458702548478000,
      "duration": 354374,
      "annotations": [
        {
          "endpoint": {
            "serviceName": "zipkin-query",
            "ipv4": "192.168.1.2",
            "port": 9411
          },
          "timestamp": 1458702548786000,
          "value": "cs"
        }
      ],
      "binaryAnnotations": [
        {
          "key": "lc",
          "value": "JDBCSpanStore",
          "endpoint": {
            "serviceName": "zipkin-query",
            "ipv4": "192.168.1.2",
            "port": 9411
          }
        }
      ]
}

traceId:标记一次请求的跟踪,相关的Spans都有相同的traceId;
id:span id;
name:span的名称,一般是接口方法的名称;
parentId:可选的id,当前Span的父Span id,通过parentId来保证Span之间的依赖关系,如果没有parentId,表示当前Span为根Span;
timestamp:Span创建时的时间戳,使用的单位是微秒(而不是毫秒),所有时间戳都有错误,包括主机之间的时钟偏差以及时间服务重新设置时钟的可能性,
出于这个原因,Span应尽可能记录其duration;
duration:持续时间使用的单位是微秒(而不是毫秒);
annotations:注释用于及时记录事件;有一组核心注释用于定义RPC请求的开始和结束;

cs:Client Send,客户端发起请求;
sr:Server Receive,服务器接受请求,开始处理;
ss:Server Send,服务器完成处理,给客户端应答;
cr:Client Receive,客户端接受应答从服务器;

binaryAnnotations:二进制注释,旨在提供有关RPC的额外信息。

3.Transport

收集的Spans必须从被追踪的服务运输到Zipkin collector,有三个主要的传输方式:HTTP, Kafka和Scribe;

4.Components

有4个组件组成Zipkin:collector,storage,search,web UI

  • collector:一旦跟踪数据到达Zipkin collector守护进程,它将被验证,存储和索引,以供Zipkin收集器查找;
  • storage:Zipkin最初数据存储在Cassandra上,因为Cassandra是可扩展的,具有灵活的模式,并在Twitter中大量使用;但是这个组件可插入,除了Cassandra之外,还支持ElasticSearch和MySQL;
  • search:一旦数据被存储和索引,我们需要一种方法来提取它。查询守护进程提供了一个简单的JSON API来查找和检索跟踪,主要给Web UI使用;
  • web UI:创建了一个GUI,为查看痕迹提供了一个很好的界面;Web UI提供了一种基于服务,时间和注释查看跟踪的方法。

三、Spring-boot中集成Zipkin示例

 

以上是关于深入探究ZIPKIN调用链跟踪——拓扑Dependencies篇的主要内容,如果未能解决你的问题,请参考以下文章

spring cloud 学习 - sleuth & zipkin 调用链跟踪

调用链系列Zipkin搭建Spring-boot集承

(56)java Spring Cloud+Spring boot+mybatis企业快速开发架构之Spring Cloud整合Zipkin进行服务跟踪

分布式链路跟踪sleuth(zipkin+kafka+elasticsearch)

使用zipkin做分布式链路监控

SpringCloud使用Zipkin实现链路跟踪