您现在的位置是:首页 >其他 >[RPC/HTTP][链路追踪]Jaeger Micro2 Gin RPC、HTTP链路追踪网站首页其他
[RPC/HTTP][链路追踪]Jaeger Micro2 Gin RPC、HTTP链路追踪
简介[RPC/HTTP][链路追踪]Jaeger Micro2 Gin RPC、HTTP链路追踪
[RPC/HTTP][链路追踪]Jaeger Micro2 Gin RPC、HTTP链路追踪
在RPC通信中,由于是分布式微服务,所以说接口之间的调用可能会变得复杂,链路之间的追踪、查看接口的健康状态,什么接口有问题,什么接口实现的时间长,这都是非常有必要观测的,链路追踪的图形化界面非常直观,这里我们就介绍一下如何使用Jaeger实现追踪过程
Jaeger
专门的链路追踪软件,可以集成在Go项目中,而且配备了一个图形化的UI界面,非常直观
- 首先,我们需要安装配置一下jaeger
docker run --rm --name jaeger -p 6831:6831/udp -p 16686:16686 jaegertracing/all-in-one:latest
这里会在16686端口下获取一个UI客户端
这里只讲述docker的办法,因为jaeger的查询还用到了es,就不多赘述了
- 然后需要在Go中导入jaeger的配置
go get "github.com/opentracing/opentracing-go"
go get "github.com/uber/jaeger-client-go"
Micro
微服务框架,我们这里使用consul作为注册中心,Micro选用的是V2,因为V2有Jaeger对应的插件,V4其实可能也有,但是博主并没有找到在哪儿。。
- 导入和V2有关的配置
"github.com/micro/go-micro/v2"
"github.com/micro/go-micro/v2/registry"
"github.com/micro/go-plugins/registry/consul/v2"
op "github.com/micro/go-plugins/wrapper/trace/opentracing/v2"
Gin
GoWeb框架,因为总会有http层的协议,我们同样可以使用Gin框架来完成http相关的操作
如何实现链路追踪?
做好相关的配置以后,我们将追踪植入到Gin的middleware中,然后同时也植入到Grpc的handler中,这样就可以将他们都链接起来了,根据上下文的信息,就可以形成不同的链路
配置Tracer
func NewJaegerTracer(serviceName, agentHostPort string) (opentracing.Tracer, io.Closer, error) {
cfg := &config.Configuration{
ServiceName: serviceName,
Sampler: &config.SamplerConfig{
Type: jaeger.SamplerTypeConst,
Param: 1,
},
Reporter: &config.ReporterConfig{
LogSpans: true,
BufferFlushInterval: 1 * time.Second,
LocalAgentHostPort: agentHostPort,
},
}
tracer, closer, err := cfg.NewTracer()
if err != nil {
return nil, nil, err
}
opentracing.SetGlobalTracer(tracer)
return tracer, closer, nil
}
写Gin的middleware
func Tracing() func(c *gin.Context) {
return func(c *gin.Context) {
var newCtx context.Context
var span opentracing.Span
//spanCtx, err := opentracing.GlobalTracer().Extract(
// opentracing.HTTPHeaders,
// opentracing.HTTPHeadersCarrier(c.Request.Header),
//)
//if err != nil {
// span, newCtx = opentracing.StartSpanFromContextWithTracer(
// c.Request.Context(),
// global.Tracer,
// c.Request.URL.Path,
// )
// //fmt.Println(c.Request.URL.Path)
//
//} else {
// fmt.Println("开始准备追踪")
// span, newCtx = opentracing.StartSpanFromContextWithTracer(
// c.Request.Context(),
// global.Tracer,
// c.Request.URL.Path,
// opentracing.ChildOf(spanCtx),
// opentracing.Tag{Key: string(ext.Component),
// Value: "HTTP",
// },
// )
span, newCtx = opentracing.StartSpanFromContextWithTracer(
c.Request.Context(),
global.Tracer,
c.Request.URL.Path,
)
defer span.Finish()
c.Request = c.Request.WithContext(newCtx)
c.Next()
}
}
在RPC服务端配置Hanlder
func main() {
fmt.Println("abc")
service2 := micro.NewService(
micro.Name("testService"),
micro.Address(":8081"),
micro.Registry(consul.NewRegistry(registry.Addrs("localhost:8500"))),
micro.WrapHandler(op.NewHandlerWrapper(global.Tracer)),
)
service2.Init()
proto.RegisterProdServiceHandler(service2.Server(), &myService.ProdService{})
service2.Run()
}
在RPC客户端配置Hanlder、配置Gin并加入中间件
func main() {
//首先建立一个客户端服务
myProdsService := micro.NewService(
micro.Name("prodsService.Client"),
micro.Registry(consul.NewRegistry(registry.Addrs("localhost:8500"))),
micro.WrapClient(op.NewClientWrapper(global.Tracer)),
)
prodsService := proto.NewProdService("testService", myProdsService.Client())
r := gin.Default()
r.Use(middleware.Tracing())
r.GET("/test", func(contextGin *gin.Context) {
var prodReq proto.ProdRequest //proto生成的请求结构体 要给他配置参数的
prodReq.Size = 3
contextGin.Bind(prodReq)
//fmt.Println(contextGin.Request.Context().
contextGin.Set("test", "TEST")
list, _ := prodsService.GetProdsList(contextGin.Request.Context(), &prodReq) //这里传递上下文对象,传递一个请求结构体
//忽略错误处理
//list就是我们想要的响应数据了 他会自己调用Call方法进行RPC协议通信
contextGin.JSON(200, gin.H{"data": list.Data})
})
r.Run()
}
启动后测试
可以看到最上层的http请求,以及接下来的RPC请求,调用什么函数都写得很清晰,谁超时出错了,谁执行完成了,谁用了多少时间,都看得很清楚了。
以上就是本博客的所有内容了,同时祝各位高考加油! 谨慎。。。 欢迎报考西安邮电大学!!
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。