关于micro:go-micro-链路追踪

6次阅读

共计 3975 个字符,预计需要花费 10 分钟才能阅读完成。

本片介绍 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 main
package main

import (
    "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 Tracer
func 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 main

import (
    "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 Tracer
func 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.go
go run cli/main.go

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



总结:

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

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

正文完
 0