链路追踪:OpenTracing SDK 与 Jaeger 的对接方法

Tags: 软件工程 

本篇目录

说明

链路跟踪就是在每个处理环节埋点,通过埋点记录每个处理环节的开始时间和结束时间,并将信息发送到链路跟踪服务,譬如 Jaeger,从而掌握了整个请求链路的处理情况。

譬如 http 请求发送时时间、接收时间、和处理过程中的每次函数调用的耗时。

准备 Jaeger

在本地启动一个 Jaeger 服务,简单起见,直接用 docker 运行:

docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:1.17.0

6831 是 Jaeger 的 udp 监听端口,用于接收埋点发送的数据,16686 是 Jageer 的页面服务端口,可以在浏览器中打开,127.0.0.1:16686:

jaeger的查看页面

Opentracing

Opentracing 项目已经归档停止开发,CNCF Archives the OpenTracing Project

OpenTracing 收集了各种语言的埋点 SDK,能与多种链路跟踪系统无缝对接, 譬如 Jaegeropentracing-go 是 OpenTracing 收录的 Go SDK,可以与 Jaeger 的 Go SDK 对接:

package main

import (
    "io"
    "log"

    opentracing "github.com/opentracing/opentracing-go"
    oplog "github.com/opentracing/opentracing-go/log"
    jaeger "github.com/uber/jaeger-client-go"
    jaegercfg "github.com/uber/jaeger-client-go/config"
    jaegerlog "github.com/uber/jaeger-client-go/log"
    "github.com/uber/jaeger-lib/metrics"
)

Jaeger 连接的初始化方法:

func initJaeger(service, addr string) (opentracing.Tracer, io.Closer, error) {
    cfg := jaegercfg.Configuration{
        ServiceName: service,
        Sampler: &jaegercfg.SamplerConfig{
            Type:  jaeger.SamplerTypeConst,
            Param: 1,
        },
        Reporter: &jaegercfg.ReporterConfig{
            LogSpans:           true,
            LocalAgentHostPort: addr,
        },
    }
    jLogger := jaegerlog.StdLogger
    jMetricsFactory := metrics.NullFactory

    return cfg.NewTracer(
        jaegercfg.Logger(jLogger),
        jaegercfg.Metrics(jMetricsFactory),
    )
}

用 opentracing-go 发送埋点数据:

//docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:latest
func main() {
    tracer, closer, err := initJaeger("00-quickstart", "127.0.0.1:6831")
    if err != nil {
        log.Fatal(err.Error())
    }
    defer closer.Close()
    opentracing.SetGlobalTracer(tracer)

    rootspan := opentracing.StartSpan("rootcall")
    defer rootspan.Finish()
    rootspan.SetTag("rootcall", "rootcall")

    subspan := opentracing.StartSpan("subcall",
        opentracing.ChildOf(rootspan.Context()))
    defer subspan.Finish()
    subspan.SetTag("subcall", "subcall")
    subspan.LogFields(oplog.String("event", "testlog"))
}

HTTP 发送端的埋点方法:

func client() {
    url := "http://localhost:8082/publish"
    req, _ := http.NewRequest("GET", url, nil)

    tracer := opentracing.GlobalTracer()

    clientSpan := tracer.StartSpan("client")
    defer clientSpan.Finish()

    ext.SpanKindRPCClient.Set(clientSpan)
    ext.HTTPUrl.Set(clientSpan, url)
    ext.HTTPMethod.Set(clientSpan, "GET")

    tracer.Inject(clientSpan.Context(), opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))
    http.DefaultClient.Do(req)
}

HTTP 接收端的埋点方法:

func server() {
    tracer := opentracing.GlobalTracer()
    http.HandleFunc("/publish", func(w http.ResponseWriter, r *http.Request) {
        spanctx, _ := tracer.Extract(opentracing.HTTPHeaders,
            opentracing.HTTPHeadersCarrier(r.Header))
        serverspan := tracer.StartSpan("server", ext.RPCServerOption(spanctx))
        defer serverspan.Finish()
    })
    log.Fatal(http.ListenAndServe(":8082", nil))
}

参考

  1. 李佶澳的博客
  2. opentracing教程
  3. yurishkuro/opentracing-tutorial
  4. opentracing-go
  5. jaegertracing
  6. CNCF Archives the OpenTracing Project

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  系统软件  程序语言  运营经验  水库文集  网络课程  微信网文  发现知识星球