本片介绍go micro中应用jaeger作为链路追踪的应用

jaeger相干常识请见官网文档,这里应用docker启动gaeger,作为测试应用

启动jaeger

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

拜访地址http://localhost:16686

go micro版本2.x,和1.x有些许不同

样例代码应用examples/greeter中代码批改
srv/mian.go

// Package mainpackage mainimport (    "context"    "io"    "time"    hello "github.com/micro/examples/greeter/srv/proto/hello"    "github.com/micro/go-micro/v2"    "github.com/micro/go-micro/v2/util/log"    wrapperTrace "github.com/micro/go-plugins/wrapper/trace/opentracing/v2"    "github.com/opentracing/opentracing-go"    "github.com/uber/jaeger-client-go"    jaegercfg "github.com/uber/jaeger-client-go/config")type Say struct{}func (s *Say) Hello(ctx context.Context, req *hello.Request, rsp *hello.Response) error {    log.Log("Received Say.Hello request")    rsp.Msg = "Hello " + req.Name    return nil}func main() {    t, io, err := NewTracer("tracer-srv", "127.0.0.1:6831")    if err != nil {        log.Fatal(err)    }    defer io.Close()    opentracing.SetGlobalTracer(t)    service := micro.NewService(        micro.Name("go.micro.srv.greeter"),        micro.WrapHandler(wrapperTrace.NewHandlerWrapper(opentracing.GlobalTracer())),    )    // optionally setup command line usage    service.Init()    // Register Handlers    hello.RegisterSayHandler(service.Server(), new(Say))    // Run server    if err := service.Run(); err != nil {        log.Fatal(err)    }}// NewTracer 创立一个jaeger Tracerfunc NewTracer(servicename string, addr string) (opentracing.Tracer, io.Closer, error) {    cfg := jaegercfg.Configuration{        ServiceName: servicename,        Sampler: &jaegercfg.SamplerConfig{            Type:  jaeger.SamplerTypeConst,            Param: 1,        },        Reporter: &jaegercfg.ReporterConfig{            LogSpans:            true,            BufferFlushInterval: 1 * time.Second,        },    }    sender, err := jaeger.NewUDPTransport(addr, 0)    if err != nil {        return nil, nil, err    }    reporter := jaeger.NewRemoteReporter(sender)    // Initialize tracer with a logger and a metrics factory    tracer, closer, err := cfg.NewTracer(        jaegercfg.Reporter(reporter),    )    return tracer, closer, err}

这里封装了`NewTracer()`创立一个jaeger Tracer

在main()中opentracing.SetGlobalTracer(t)设置给opentracing

micro的wrapper有4种:

  1. WrapHandler() server中间件
  2. WrapCall() call中间件
  3. WrapClient() client中间件
  4. WrapSubscriber() 订阅中间件

server端咱们应用micro.WrapHandler()

通过micro plugins自带的opentracing插件设置下

wrapperTrace.NewHandlerWrapper(opentracing.GlobalTracer())

cli/mian.go

package mainimport (    "context"    "fmt"    "io"    "log"    "time"    hello "github.com/micro/examples/greeter/srv/proto/hello"    "github.com/micro/go-micro/v2"    wrapperTrace "github.com/micro/go-plugins/wrapper/trace/opentracing/v2"    "github.com/opentracing/opentracing-go"    "github.com/uber/jaeger-client-go"    jaegercfg "github.com/uber/jaeger-client-go/config")func main() {    t, io, err := NewTracer("tracer-cli", "127.0.0.1:6831")    if err != nil {        log.Fatal(err)    }    defer io.Close()    opentracing.SetGlobalTracer(t)    // ctx, span, err := wrapperTrace.StartSpanFromContext(context.Background(), opentracing.GlobalTracer(), "root")    // create a new service    service := micro.NewService(        micro.WrapClient(wrapperTrace.NewClientWrapper(opentracing.GlobalTracer())),    )    // parse command line flags    service.Init()    // Use the generated client stub    cl := hello.NewSayService("go.micro.srv.greeter", service.Client())    // Make request    rsp, err := cl.Hello(context.Background(), &hello.Request{        Name: "John",    })    if err != nil {        fmt.Println(err)        return    }    fmt.Println(rsp.Msg)}// NewTracer 创立一个jaeger Tracerfunc NewTracer(servicename string, addr string) (opentracing.Tracer, io.Closer, error) {    cfg := jaegercfg.Configuration{        ServiceName: servicename,        Sampler: &jaegercfg.SamplerConfig{            Type:  jaeger.SamplerTypeConst,            Param: 1,        },        Reporter: &jaegercfg.ReporterConfig{            LogSpans:            true,            BufferFlushInterval: 1 * time.Second,        },    }    sender, err := jaeger.NewUDPTransport(addr, 0)    if err != nil {        return nil, nil, err    }    reporter := jaeger.NewRemoteReporter(sender)    // Initialize tracer with a logger and a metrics factory    tracer, closer, err := cfg.NewTracer(        jaegercfg.Reporter(reporter),    )    return tracer, closer, err}

client端减少的代码和server基本一致,

只是micro.NewService()中应用的是中间件是micro.WrapClient()

同时参数相应的变为wrapperTrace.NewClientWrapper(opentracing.GlobalTracer())

运行起来

go run srv/main.gogo run cli/main.go

刷新http://localhost:16686/即可看到



总结:

  1. go micro 在整个申请周期中都会带着ctx,放入header中,详情请见【micro server剖析】,链路追踪的原理就是在header中拿到追踪信息,存入剖析工具并解析,再展示到页面。
  2. 链路追踪不仅能够用于追踪整个申请周期,还可自定义追踪某几行代码,具体请见官网文档

参考【go-micro实际】jaeger分布式链路追踪