使用otgrpc配合jaeger在grpc调用链中实现追踪
1.下载otgrpc源码:
2.修改源码:在client.go文件48行加入
ginContext := ctx.Value("ginContext") switch ginContext.(type) { case *gin.Context: if itracer, ok := ginContext.(*gin.Context).Get("tracer"); ok { tracer = itracer.(opentracing.Tracer) } if parentSpan, ok := ginContext.(*gin.Context).Get("parentSpan"); ok { parentCtx = parentSpan.(*jaeger.Span).Context() } }
在server.go文件36行加入
if info.FullMethod != "/grpc.health.v1.Health/Check" {
在server.go文件72行加入
} else { resp, err = handler(ctx, req) return resp, err }
在 gin 中添加中间件:
package middlewares import ( "github.com/gin-gonic/gin" "github.com/uber/jaeger-client-go" jaegercfg "github.com/uber/jaeger-client-go/config" ) func Trac() gin.HandlerFunc { return func(c *gin.Context) { cfg := jaegercfg.Configuration{ Sampler: &jaegercfg.SamplerConfig{ Type: jaeger.SamplerTypeConst, Param: 1, }, Reporter: &jaegercfg.ReporterConfig{ LogSpans: true, LocalAgentHostPort: "192.168.0.104:6831", }, ServiceName: "mxshop", } tracer, closer, err := cfg.NewTracer(jaegercfg.Logger(jaeger.StdLogger)) if err != nil { return } defer closer.Close() startSpan := tracer.StartSpan(c.Request.URL.Path) defer startSpan.Finish() c.Set("tracer", tracer) c.Set("parentSpan", startSpan) c.Next() } }
func InitGoodsRouter(Router *gin.RouterGroup) { r := Router.Group("/goods").Use(middlewares.Trac()) //修改此处 { r.GET("/list", goods.List) r.GET("/detail/:id", goods.Detail) r.POST("/batch", goods.Batch) r.POST("/create", middlewares.JWTAuth(), middlewares.IsAdmin(), goods.Create) r.DELETE("/:id", middlewares.JWTAuth(), middlewares.IsAdmin(), goods.Delete) r.PUT("/:id", middlewares.JWTAuth(), middlewares.IsAdmin(), goods.Update) r.PATCH("/:id", middlewares.JWTAuth(), middlewares.IsAdmin(), goods.UpdateStatus) } }
在连接grpc服务端处添加一个拦截器:
conn, err := grpc.Dial(fmt.Sprintf("consul://%s:%d/%s?wait=1s", host, port, global.ServerConfig.Goods.Name), grpc.WithInsecure(), grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`), grpc.WithUnaryInterceptor(otgrpc.OpenTracingClientInterceptor(opentracing.GlobalTracer())), //这一行是添加的拦截器代码 ) closeAllClientConn()
在调用grpc服务端方法处修改context:
list, err := global.GoodsClient.GoodsList(context.WithValue(context.Background(), "ginContext", ctx), &req) //目的是将gin的*gin.context对象传入context中 context.WithValue(context.Background(), "ginContext", ctx)
在grpc服务端NewServer时添加一个拦截器:
cfg := jaegercfg.Configuration{ Sampler: &jaegercfg.SamplerConfig{ Type: jaeger.SamplerTypeConst, Param: 1, }, Reporter: &jaegercfg.ReporterConfig{ LogSpans: true, LocalAgentHostPort: "192.168.0.104:6831", }, ServiceName: "mxshop", } tracer, closer, err := cfg.NewTracer(jaegercfg.Logger(jaeger.StdLogger)) if err != nil { return } defer closer.Close() server := grpc.NewServer(grpc.UnaryInterceptor(otgrpc.OpenTracingServerInterceptor(tracer))) //这里把上面生成的tracer传入
在grpc服务端方法中获取父span:
import "github.com/opentracing/opentracing-go" //需要把这个玩意引入进来 ... parentSpan := opentracing.SpanFromContext(o.Ctx) //此处的ctx就是 grpc方法中的(ctx context.Context)参数
在grpc服务端方法中添加子span:
goodsSpan := opentracing.GlobalTracer().StartSpan("goods_span", opentracing.ChildOf(parentSpan.Context())) //指明父span goods, err := global.GoodsClient.BatchGetGoods(context.Background(), &protoGoods.BatchGoodsIdInfo{ //grpc调用其他微服务 Id: goodsIds, }) goodsSpan.Finish() //调用完毕之后要及时 Finish
访问gin路由网址之后,我们来查看jaegerUI界面:
发表评论