go micro 链路追踪

舞林 · · 1079 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本片介绍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/即可看到

image
image
总结:

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

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

go micro 分析系列文章
go micro server 启动分析
go micro client
go micro broker
go micro cmd
go micro config
go micro store
go micro registry
go micro router
go micro runtime
go micro transport
go micro web
go micro registry 插件consul
go micro plugin
go micro jwt 网关鉴权
go micro 链路追踪
go micro 熔断与限流
go micro wrapper 中间件
go micro metrics 接入Prometheus、Grafana


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:舞林

查看原文:go micro 链路追踪

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1079 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传