Jaeger-分布式调用链跟踪系统理论与实战

导语

调用链跟踪系统,又称为tracing,是微服务设计架构中,从系统层面对整体的monitoring和profiling的一种技术手段,而Jaeger则是Uber开发的新一代tracing系统。

1. 背景说明

由于我们的项目是微服务方向,中后台服务现在已经有10多类左右服务模块,且各个服务/模块之间的调用关系复杂,部分服务与服务之间还存在一些proxy服务(实现服务的多活部署)。这些现象就导致在开发调试、问题跟踪上都会逐步出现问题。因此,前段时间对当前微服务中较流行的两款开源分布式tracing系统:Zipkin和Jaeger分别进行了调研。

Zipkin(github ,homepage),是一款由java开发的分布式追踪系统。在微服务架构下,它用于帮助收集排查潜在问题的时序数据,同时管理数据收集和数据查询。

Jaeger(github ,homepage),则是受Dapper和OpenZipkin启发,由Uber使用golang开发的分布式跟踪系统。由于我们项目的技术栈为golang,所以重点调研了Jaeger并在此列出。

2. 跟踪链

首先,简要说下什么是跟踪链,如果有相关基础的同学可以略过,或者也可以快速过一下该段。基本上,任何说到跟踪链相关的文章,都会贴出下面这张图:

图 1. 一个简单的tracing调用过程

图1是Google的Dapper论文里的一个例子:图示中,A~E五个节点表示五个服务。用户发起一次请求RequestX到A,同时由于该请求依赖服务B与C,因此A分别发送RPC请求到B和C,B处理完请求后会直接返回到A,但是服务C还依赖服务D和E,因此还要发起两个RPC请求分别到D和E,D和E处理完毕后回到C,C才继续回复到A,最终A会回复用户ReplyX。对于这样一个请求,简单实用的分布式跟踪的实现,就是为服务器上每一次发送和接收动作来收集跟踪标识符和时间戳。

在Dapper这篇论文中,Trace和Span是两个很重要的名词。我们使用Trace表示对一次请求完整调用链的跟踪,而将两个服务例如上面的服务A和服务B的请求/响应过程叫做一次Span,trace是通过span来体现的, 通过一句话总结,我们可以将一次trace,看成是span的有向图,而这个有向图的边即为span。为了可以更好的理解这两个名词,我们可以再来看一下面的调用图。

        [Span A]  ←←←(the root span)
            |
     +------+------+
     |             |
 [Span B]      [Span C] ←←←(Span C is a `ChildOf` Span A)
     |             |
 [Span D]      +---+-------+
               |           |
           [Span E]    [Span F] >>> [Span G] >>> [Span H]
                                       ↑
                                       ↑
                                       ↑
                         (Span G `FollowsFrom` Span F)上图中,包含了8个span信息

图 2. 某次tracing过程的spans关系图

––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time
 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······]        [Span F··] [Span G··] [Span H··]

图 3. Spans的时间轴关系图

而分布式跟踪系统要做的,就是记录每次发送和接受动作的标识符和时间戳,将一次请求涉及到的所有服务串联起来,只有这样才能搞清楚一次请求的完整调用链。 

3. OpenTracing

在具体介绍Jaeger之前,还需要赘述一下另一个关键词:OpenTracing。

一句话总结,OpenTracing是一套标准,它通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现(我们在测试使用中是基本上通过两行代码的更改就可以在Zipkin和Jaeger之间切换)。OpenTracing提供了用于运营支撑系统的和针对特定平台的辅助程序库。程序库的具体信息请参考详细的规范。OpenTracing 已进入 CNCF(云原生计算基金会,著名的Kubernetes、gRPC和Prometheus等均孵化于此),正在为全球的分布式追踪,提供统一的概念和数据标准。

当然,本文之前提到的Zipkin和Jaeger,都是支持OpenTracing标准的。

3.1 引用关系

OpenTracing标准中目前定义了两种类型的引用: 

  1. ChildOf; 
  2. FollowsFrom;  两种参考类型都具体模拟了child span与parent span之间的直接因果关系。  未来,OpenTracing还可能支持带有非因果关系的Spans的引用类型(例如,一起批量化的Spans,停留在同一队列中的Spans等)。

3.1.1 ChildOf引用

一个span A可以是ChildOf另一个span B。以下所有内容均构成ChildOf关系: 

  1. 代表RPC服务器端的Span,可以是ChildOf代表该RPC客户端的span 
  2. 代表SQL插入的Span,可以是ChildOf代表ORM save方法的Span  通过时序图来看,如下所示:
[-Parent Span---------]
         [-Child Span----]
    [-Parent Span--------------]
         [-Child Span A----]
          [-Child Span B----]
        [-Child Span C----]
         [-Child Span D---------------]
         [-Child Span E----]

图 4. Span的ChildOf引用

3.1.2 FollowsFrom引用

一些parent Spans不以任何方式依赖他们的child Spans的结果。 在这些情况下,我们只说child Span从因果意义上来自parent Span。

4. Jaeger介绍

如果细心的话,通过上面CNCF的地址,我们可以发现,Jaeger现在也成为了CNCF的孵化项目。

为了深入了解下jaeger的工作原理,首先,我们来看一下Jaeger的架构设计图:

图 5. Jaeger架构设计图

在上图,我们看到Jaeger系统中:黄色部分是我们的应用程序代码;红色部门表示instrument操作,即把我们应用程序与jaeger-client装载起来,从而开始了应用程序到Jaeger的的数据交互操作。将该部分放大来看,我们可以参考下图,了解详细的数据交互方式:

图 6. Jaeger的instrumentation过程

在图5中,我们可以观察到Jaeger的完整的概览设计。从中我们会发现Jaeger有5个模块元素,如下所列出,接下来我们来分别解释这五个模块的作用:

1.Jaeger-client
2.Agent
3.Collector
4.Data Store
5.UI

Jaeger-client(客户端库)

client是客户端lib,便于不同语言的项目来介入到Jaeger中,当我们的应用程序装载上之后,client会负责收集并发送数据到Agent。当前Jaeger的SDK支持有如下:

--官方 
1.Go 
2.Java 
3.Node 
4.Python 
5.C++ 
--非官方 
1.PHP
3.Others

client是支持OpenTracing标准的,如上文提到,Zipkin也是支持OpenTracing标准的,这也就意味着,我们的应用程序在嵌入Jaeger-client的地方,可以随时替换成Zipkin,对业务是完全透明的。

Agent(客户端代理)

jaeger的agent,是一个监听在 UDP 端口上接收 span 数据的网络守护进程。 如同大多数分布式系统都拥有一个Agent一样,Jaeger的Agent有以下几类特点:

agent收集并汇聚这些span信息到collector;

agent的被设计成一个基础组件,旨在作为基础架构组件部署到所有宿主机

agent将client library 和 collector 解耦,为 client library 屏蔽了路由和发现 collector 的细节;

Collector(数据收集处理)

collector,顾名思义,从agent收集traces信息,并通过处理管道处理他们,再写入后端存储(backends)。 

当前的collector工作主要是管理trace,建立索引,执行相关转换,并最终存储它们。

Collector中运行着sampling逻辑,根据我们设定的sampling方式对数据进行收集和处理。

Data Store(数据存储)

jaeger的data store是组件的方式。 

当前可以支持 Cassandra和ElasticSearch(当然也支持纯内存方式,但是不适用于生产环境).

Query & UI(数据查询与前端界面展示)

Query查询是一种从存储中检索trace,并提供UI以显示它们的服务。上图中就展示了一次Trace的数据流向,作为一次系统作用的数据传播/执行图,即可以在Jaeger UI上展示出来。

5. 部署方式

Jaeger的部署由于方案的不同,会依赖不同的服务,这些第三方基础服务的部署安装不再该文范围内,如docker、Elasticsearch、Cassandra等

5.1 All in one

为了方便大家快速使用,Jaeger直接提供一个All in one的docker镜像,通过All in one的image,我们可以通过以下命令直接启动一套完整的Jaeger tracing系统:

$ docker run -d -e \
  COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
  -p 5775:5775/udp \
  -p 6831:6831/udp \
  -p 6832:6832/udp \
  -p 5778:5778 \
  -p 16686:16686 \
  -p 14268:14268 \
  -p 9411:9411 \
  jaegertracing/all-in-one:latest

 一旦启动成功后,就可以去http://localhost:16686看到Jaeger UI了,如下所示。

图 7. Jaeger UI的首页

注:在All in one模式下,Data Store使用的是内存,因此若重启dockre容器后就看不到之前的数据了。所以,该模式仅可用于前期demo或者验证,不可在生产环境中这样部署。

5.2 独立部署

当然我们更推荐的方式是独立部署,独立部署也可以分为docker镜像方式和binary 方式,官网有详细的docker镜像方式启动命令介绍,在这儿就不再粘贴复制了。

关于binary方式部署,可以参看github上的Jaeger的二进制包。地址提供了mac、linux和windows的三大操作系统的binary包。以linux为例,解压后我们可以发现有以下几个bin包,分别清晰地对应了我们之前说的几个模块:

drwxrwxr-x 3 2000 2000 4.0K May 28 23:29 jaeger-ui-build
-rwxrwxr-x 1 2000 2000  27M May 28 23:29 jaeger-standalone
-rwxrwxr-x 1 2000 2000  22M May 28 23:29 jaeger-query
-rwxrwxr-x 1 2000 2000  25M May 28 23:29 jaeger-collector
-rwxrwxr-x 1 2000 2000  16M May 28 23:29 jaeger-agent

注:Jaeger同时也提供可Kubernetes and OpenShift的模板。可参考github地址有详细介绍

5.3 端口说明

通过上述All in one启动方式,我们直接发现了Jaeger启动时占据了很多端口,当然,并不是所有的端口都是必需的,这儿简单列出这些端口的说明如下:

端口	协议	所属模块	     功能
5775	UDP	agent	     通过兼容性Thrift协议,接收Zipkin thrift类型数据
6831	UDP	agent	     通过兼容性Thrift协议,接收Jaeger thrift类型数据
6832	UDP	agent	     通过二进制Thrift协议,接收Jaeger thrift类型数据
5778	HTTP	agent	     配置控制服务接口
16686	HTTP	query	     客户端前端界面展示端口
14268	HTTP	collector    接收客户端Zipkin thrift类型数据
14267	HTTP	collector    接收客户端Jaeger thrift类型数据
9411	HTTP	collector    Zipkin兼容endpoint

 6. Sampling

关于Jaeger系统中的采样方式,我们可以通过一个例子来解释。

假设有三个服务A,B,C,且存在一个简单的调用方式:A->B->C, 当服务A收到请求时,Jaeger检查该请求有没有trace信息,如果没有,将为其生成新的trace(TraceId为随机生成的),并基于当前的取样策略进行sampling。该取样策略会随着请求一路广播到服务B和C,因此这些服务将必须再做采样的策略选择。这种采样方式确保了当一个trace被采用后,它的所有后续spans都会被存储起来(若每层服务都再做一次采样策略选择的话,我们就会很难获取到完整的一个trace了)。

7. 代码侵入性

关于装载的方法,不同语言在网上的代码示例都很多。对于tracing这种监控类系统,一定不能对我们的业务代码侵入太高,因为我们的项目代码为golang,下面以golang代码中grpc下,jaeger的代码侵入性比较(为了提高可读性,直接展示出diff信息):

图 8. tracing的代码侵入展示

我们看到,利用grpc的interceptor功能,jager只需要在拦截器中插入一个interceptor即可,整体代码的影响之有5行左右。(注:在业务代码中,grpc使用context来携带信息)

8. Jaeger使用

当我们正是使用jager后,可以通过两种方式来进行查看:

根据TraceId搜索

通过Web UI左上方,可以直接键入TraceId进行某次trace的搜索

根据服务节点查看

通过Web UI左边栏Find Traces,可以详细地进行高级搜索功能,支持服务名,操作,Tag信息(Jaeger中的tag功能,可以在context中加入tag,进行更过的标识)等。当我们确定搜索条件后,就可以查出符合条件的trace信息了,下图为我们一个腾讯云cos代理业务程序的简单请求示例:

图 9. Jaeger的使用展示

上面就是本次文章的所有内容,有感兴趣或有疑问的小伙伴欢迎讨论和留言

相关链接:

http://opentracing.io/documentation/pages/spec.html

https://www.jaegertracing.io

https://github.com/jaegertracing/jaeger

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CDA数据分析师

Python 爬虫的工具列表

这个列表包含与网页抓取和数据处理的Python库 网络 通用 urllib -网络库(stdlib)。 requests -网络库。 grab – 网络库(基于...

37710
来自专栏java达人

java 与 python 的并发争论

有一天,java遇到了python兄弟,调侃道:“我听一位刚学python的老伙计道,你这并发包很不好用呀。” “怎么不好用了,我有Threading模块,只...

5049
来自专栏五毛程序员

五毛的cocos2d-x学习笔记01-创建项目

1734
来自专栏海纳周报

多线程内幕

本文是HinusWeekly第三期的第二篇文章,第三期的主题就是多线程编程。本文试图从单核CPU的角度讨论并发编程的困难。 函数调用的过程,就是不断地创建栈帧,...

3558
来自专栏QQ会员技术团队的专栏

经验之道:最有效的 iOS 内存泄漏检测

通过过去参与过的复杂大型的iOS项目开发经验,开发新的模块的时候,总结出了一套完整的iOS内存自测的方法,通过Instruments来逐步跟踪检测我们创建和主动...

7K0
来自专栏令仔很忙

三层架构(一)——什么是三层架构?

三层架构(3-tier architecture) 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)。...

6012
来自专栏北京马哥教育

快收藏!史上最全156个Python网络爬虫资源

awesome系列真是碉堡了~今天把Python的爬虫工具搬过来~ ——————译文分割线—————— 本列表包含Python网页抓取和数据处理相关的库。 网络...

3714
来自专栏拂晓风起

node.js WebService异常处理(domain)以及利用domain实现request生命周期的全局变量

1653
来自专栏北京马哥教育

干货 | 史上最全的 Python 爬虫工具列表大全

来源:伯乐在线 这个列表包含与网页抓取和数据处理的Python库。 网络 通用 urllib -网络库(stdlib)。 requests -网络库。 gra...

75214
来自专栏Python学习心得

​Python爬虫--- 1.5 爬虫实践: 获取百度贴吧内容

原文链接:https://www.fkomm.cn/article/2018/7/22/21.html

1020

扫码关注云+社区

领取腾讯云代金券