本片介绍go micro中使用jaeger作为链路追踪的使用
jaeger相关知识请见官方文档,这里使用docker启动gaeger,作为测试使用
启动jaeger
docker run -d -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:latest
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种:WrapHandler() server中间件
WrapCall() call中间件
WrapClient() client中间件
WrapSubscriber() 订阅中间件
server端我们使用micro.WrapHandler()
通过micro plugins自带的opentracing插件设置下
wrapperTrace.NewHandlerWrapper(opentracing.GlobalTracer())
cli/mian.gopackage 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
总结:go micro 在整个请求周期中都会带着ctx,放入header中,详情请见【micro server分析】,链路追踪的原理就是在header中拿到追踪信息,存入分析工具并解析,再展现到页面。
链路追踪不仅可以用于追踪整个请求周期,还可自定义追踪某几行代码,具体请见官方文档
有疑问加站长微信联系(非本文作者)