Jaeger OpenTracing 体验

文章目录

    • Jaeger OpenTracing
    • Jaeger架构图和组件
      • 架构图
      • 组件1 : Instrumentation + OpenTracing API
      • 组件2 : Jaeger-client
      • 组件3 : Jaeger-agent
      • 组件4 : Jaeger-collector
      • 组件5 : Jaeger-query
    • 搭建Demo流程[ES]
    • 代码解析
    • 效果图
    • 代码
    • 最后

Jaeger OpenTracing

Jaeger项目地址
OpenTracing-Golang项目地址
这个Jaeger是Uber的分布式追踪系统,可以说是调用链追踪吧,这些调用链追踪系统都是参照Dapper。这里有一个中文版翻译,可以看看:
Dapper 翻译
按照我的理解,应该就是给一个调用链一个全局ID,无论是走RPC调用还是直接Restful HTTP调用,都需要带着这个ID,这样就可以形成一个链,根据这个ID就可以把Span的信息全部串起来了。

Jaeger架构图和组件

架构图

这里盗张图,Jaeger官网:
Jaeger OpenTracing 体验_第1张图片
刚开始看到这张图我也是懵逼的,怎么会有这么多东西,这几个怎么串起来的,跟OpenTracing又是啥关系,怎么把Data Store换成ES或者kafka。我也是慢慢看文档,然后试出来的,后面的会给一个具体流程,希望有帮助。
下面看下各个组件

组件1 : Instrumentation + OpenTracing API

这两个是连在一块儿的,这两个东西都是插在我们业务代码里面的,就是要在我们的代码里面加入OpenTracing的代码。OpenTracing提供了很多语言的API,详细的可以看看上面的GitHub。对于Golang来说,主要的就是下面几个API:

opentracing.SetGlobalTracer()  //设置全局的tracer
opentracing.StartSpan() //开始一个span
opentracing.GlobalTracer().Inject() //把span信息注入到http请求里面
opentracing.GlobalTracer().Extract()  //从http请求里面解析出上一个服务的span信息

可以看到上面的SetGlobalTracer是可以设置成其他的tracer的,比如zipkin其他的,如果需要改动tracer的话,就只需要改这个参数即可,不需要改动其他插入的代码。

组件2 : Jaeger-client

Jaeger的客户端就相当于上面的tracer,在代码里面SetGlobalTracer的时候,参数传的就是Jaeger-client New出来的一个实例。既然是客户端,那么服务端是什么呢?服务端是Jaeger-agent。

组件3 : Jaeger-agent

这个是Jaeger的服务端,客户端会把Span的信息通过Jaeger.Thrift UDP传给Jaeger-agent,再由Jaeger-agent把这些span的信息传给Jaeger-collector。

为啥不直接把信息传到collector?从上面的图我猜测,collector应该是对agent有采样率的限制,在代码里面可以看到相关的设置。

组件4 : Jaeger-collector

负责把Jaeger-agent传过来的数据写入队列,并且保存到设定的存储介质里面[内存,ES,kafka…]

组件5 : Jaeger-query

这个是负责从存储介质里面读取调用链信息的,并且这个query自带UI,可以在UI里面看到相关的调用链。

搭建Demo流程[ES]

  1. 由于现在官网上面只支持ES5 和 ES6,所以我们可能不能使用最新的ES7,所以我们下载ES6:
    ES6
  2. 下载Jaeger相关组件二进制文件:
    Jaeger二进制文件
  3. 安装ES6,这个应该解包就能使用。
  4. 先启动ES,最好先启动ES,因为启动collector需要ES。
  5. 清除ES里面的相关index 清除index脚本
  6. 设置collector的环境变量,并且启动collector。
  7. 启动agent。
  8. 启动query。
#!/bin/bash
wget es.tar.gz
tar -xvzf es.tar.gz
wget jaeger.tar.gz
tar -xvzf jaeger.tar.gz
cd es/bin && ./elasticsearch
cd jaeger/bin
export SPAN_STORAGE_TYPE=elasticsearch
./jaeger-collector --es.server-urls=http://192.168.26.83:9200
./jaeger-agent --reporter.tchannel.host-port=192.168.26.83:14267
./jaeger-query --es.server-urls http://192.168.26.83:9200

上面的export是必须的,千万别忘了。第五点也是重点!!!
上面的export是必须的,千万别忘了。第五点也是重点!!!
上面的export是必须的,千万别忘了。第五点也是重点!!!
如果不出意外的话,lsof -i的话可以看到类似于下面的这张图:
Jaeger OpenTracing 体验_第2张图片
从上面可以看到:
① 黄色框里面的内容:agent和collector建立了连接,14267这个端口的作用在文档里面有说:

14267- - - TChannel - - -used by jaeger-agent to send spans in jaeger.thrift format
是agent发送span给collector的通道

② 蓝色框里面的内容:分别是query组件和collector组件跟ES建立的连接,collector负责往ES里面写,query负责从ES里面读。

③ 红色框是代码里面初始化Jaeger-client之后,client跟agent建立起的连接,6831这个接口在文档里面有说:

6831- - - UDP- - -accept jaeger.thrift over compact thrift protocol
是client发送信息给agent的通道,通过thrift协议

现在应该就通了:
client生成的span信息通过6831发送到agent,agent再根据采样率来筛选记录,再通过14267传给collector,collector再通过9200往ES里面写,query通过9200从ES里面读并提供UI。

代码解析

最关键的就是Jaeger的初始化和OpenTracing的初始化:

 //这个是初始化jaeger-client的配置,包括采样率和报告方式
    cfg = jaegercfg.Configuration {
        Sampler : &jaegercfg.SamplerConfig {
            Type : "const",
            Param : 1,
        },  
        Reporter : &jaegercfg.ReporterConfig {
            LogSpans : true,
        },  
    }   
    
// 这个是创建jaeger-client,现在我们就可以得到一个jaeger tracer了
    tracer, closer, err := cfg.New(
        "elasticSearch-Jaeger",
        jaegercfg.Logger(jLogger),
        jaegercfg.Metrics(jMetricsFactory),
    )
    
//把OpenTracing的tracer设置成jaeger
    opentracing.SetGlobalTracer(tracer)
    
// 开始一个Span
    sp := opentracing.StartSpan("get_function")
    
// 创建子Span
    sp := opentracing.StartSpan(
        "one_function",
        opentracing.ChildOf(parentSpan.Context()))
        
// 结束span记录
	sp.Finish()
	
// 追加span 日志
sp.LogFields(
        openlog.String("Function_Name", logString),
        openlog.Int("Wating millis", 1000))

// 远程调用之前需要往请求里面注入当前的span信息:
    opentracing.GlobalTracer().Inject(
        sp.Context(),
        opentracing.HTTPHeaders,
        opentracing.HTTPHeadersCarrier(httpReq.Header))

// 远程调用响应时需要解析调用的span:
    wireContext, err := opentracing.GlobalTracer().Extract(
        opentracing.HTTPHeaders,
        opentracing.HTTPHeadersCarrier(r.Header))
    sp = opentracing.StartSpan(
        "second_service_function",
        ext.RPCServerOption(wireContext))

效果图

我们使用PostMan发送请求之后,可以在Jaeger-UI里面看到相关的调用链:
Jaeger OpenTracing 体验_第3张图片
跟代码里面的sleep的时间是对应的上的,并且层级关系也很清楚。

如果你也启动了Kibana的话,那么在Kibana的页面也可以看到Span的相关信息:
Jaeger OpenTracing 体验_第4张图片

代码

GitHub

最后

这个只是Demo,并且采样率设置的是每一条记录都需要收集,具体的参数还需要查阅文档或者代码,这边博客的目的在于了解并且开始熟悉OpenTracing,之前我对于这个OpenTracing的概念是模糊的,而且加上了Jaeger之后我更懵逼了, 通过一个星期的自学,我自己走了一遍流程,发现还是可以按照文档做出来一个Demo的,还是算比较欣慰吧,希望能帮助到大家。

你可能感兴趣的:(Golang,工具)