go-kit 微服務 服務鏈路追蹤 (jaeger 實現)(1)
go-kit 微服務 服務鏈路追蹤(jaeger 實現)(1)
- 對 grpc 呼叫新增鏈路追蹤
部署 jaeger
- 生產環境部署
- Docker Hub 中有官方打好的 Image https://hub.docker.com/u/jaegertracing/
-
本地測試
-
可以直接用 Jaeger 的 all-in-one
sudo docker pull jaegertracing/all-in-one sudo docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp -p5778:5778 -p16686:16686 -p14268:14268 -p9411:9411 jaegertracing/all-in-one:latest
能正常訪問 http://127.0.0.1:16686/ 則安裝成功
-
編寫 jaeger 關於 grpc 程式碼
初始化客戶端
func NewJaegerTracer(serviceName string) (tracer opentracing.Tracer, closer io.Closer, err error) {
cfg := &jaegerConfig.Configuration{
Sampler: &jaegerConfig.SamplerConfig{
Type: "const", //固定取樣
Param: 1, //1=全取樣、0=不取樣
},
Reporter: &jaegerConfig.ReporterConfig{
LogSpans: true,
LocalAgentHostPort: "127.0.0.1:6831",
},
ServiceName: serviceName,
}
tracer, closer, err = cfg.NewTracer(jaegerConfig.Logger(jaeger.StdLogger))
if err != nil {
return
}
opentracing.SetGlobalTracer(tracer)
return
}
grpc 客戶端中介軟體
func JaegerClientMiddleware(tracer opentracing.Tracer) grpc.UnaryClientInterceptor {
return func(
ctx context.Context,
method string,
req, resp interface{},
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption,
) error {
var parentCtx opentracing.SpanContext
//先判斷ctx裡面有沒有 span 資訊
//沒有就生成一個
if parent := opentracing.SpanFromContext(ctx); parent != nil {
parentCtx = parent.Context()
}
cliSpan := tracer.StartSpan(
method,
opentracing.ChildOf(parentCtx),//父子關係的span關係
TracingComponentTag,//grcp tag
ext.SpanKindRPCClient,//客戶端 tag
)
defer cliSpan.Finish()
//從context中獲取metadata。md.(type) == map[string][]string
md, ok := metadata.FromOutgoingContext(ctx)
if !ok {
md = metadata.New(nil)
} else {
////如果對metadata進行修改,那麼需要用拷貝的副本進行修改。
md = md.Copy()
}
//定義一個carrier,下面的Inject注入資料需要用到。carrier.(type) == map[string]string
//carrier := opentracing.TextMapCarrier{}
mdWriter := MDReaderWriter{md}
////將span的context資訊注入到carrier中
err := tracer.Inject(cliSpan.Context(), opentracing.TextMap, mdWriter)
if err != nil {
grpclog.Errorf("inject to metadata err %v", err)
}
////建立一個新的context,把metadata附帶上
ctx = metadata.NewOutgoingContext(ctx, md)
err = invoker(ctx, method, req, resp, cc, opts...)
if err != nil {
cliSpan.LogFields(log.String("err", err.Error()))
}
return err
}
}
grpc 服務端中介軟體
func JaegerServerMiddleware(tracer opentracing.Tracer) grpc.UnaryServerInterceptor {
return func(
ctx context.Context,
req interface{},
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (resp interface{}, err error) {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
md = metadata.New(nil)
}
spanContext, err := tracer.Extract(opentracing.TextMap, MDReaderWriter{md})
if err != nil && err != opentracing.ErrSpanContextNotFound {
grpclog.Errorf("extract from metadata err %v", err)
}
serverSpan := tracer.StartSpan(
info.FullMethod,
ext.RPCServerOption(spanContext),
TracingComponentTag,
ext.SpanKindRPCServer,
)
defer serverSpan.Finish()
ctx = opentracing.ContextWithSpan(ctx, serverSpan)
return handler(ctx, req)
}
}
修改服務端方法
......
tracer, _, err := utils.NewJaegerTracer("user_agent_server")
if err != nil {
utils.GetLogger().Warn("[user_agent] NewJaegerTracer", zap.Error(err))
quitChan <- err
}
Registar.Register()
utils.GetLogger().Info("[user_agent] grpc run " + *grpcAddr)
chainUnaryServer := grpcmiddleware.ChainUnaryServer(
grpctransport.Interceptor,
tils.JaegerServerMiddleware(tracer),
)
baseServer := grpc.NewServer(grpc.UnaryInterceptor(chainUnaryServer))
pb.RegisterUserServer(baseServer, grpcServer)
quitChan <- baseServer.Serve(grpcListener)
......
修改客戶端程式碼
......
tracer, _, err := utils.NewJaegerTracer("user_agent_client")
if err != nil {
return nil, err
}
......
......
conn, err := grpc.Dial(instance, grpc.WithInsecure(),
grpc.WithUnaryInterceptor(utils.JaegerClientMiddleware(u.tracer)), )
if err != nil {
return nil, nil, err
}
srv := u.NewGRPCClient(conn)
......
執行
- 執行 TestNewUserAgentClient 方法
- 我們登入 http://127.0.0.1:16686/ jaeger 後臺查詢資訊
結語
- 通過後臺介面我們可以看到請求資訊,以便與我們對服務的瞭解
- jaeger 的用法還有很多,這裡只展示簡單的使用,更加高階的功能歡迎大家一起討論
- 歡迎新增 QQ 一起討論
完整程式碼地址
參考文獻
聯絡 QQ: 3355168235
更多原創文章乾貨分享,請關注公眾號
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- go-kit 微服務 服務鏈路追蹤 (jaeger 實現)(2)Go微服務
- go-kit微服務:服務鏈路追蹤Go微服務
- (16)go-micro微服務jaeger鏈路追蹤Go微服務
- 利用Spring Boot實現微服務的鏈路追蹤Spring Boot微服務
- 分散式鏈路追蹤Jaeger + 微服務Pig在Rainbond上的實踐分享分散式微服務AI
- 詳解ElasticAPM實現微服務的鏈路追蹤(NET)AST微服務
- 微服務鏈路追蹤元件 SkyWalking微服務元件
- Asp.Net Core&Jaeger實現鏈路追蹤ASP.NET
- go-kit 微服務 服務監控 (prometheus 實現)Go微服務Prometheus
- net core 微服務框架 Viper 呼叫鏈路追蹤微服務框架
- 微服務呼叫鏈追蹤中心搭建微服務
- 微服務整合Spring Cloud Zipkin實現鏈路追蹤並整合Dubbo微服務SpringCloud
- go-zero docker-compose 搭建課件服務(八):整合jaeger鏈路追蹤GoDocker
- 微服務 Zipkin 鏈路追蹤原理(圖文詳解)微服務
- 微服務追蹤SQL上報至Jaeger(支援Istio管控下的gorm查詢追蹤)微服務SQLGoORM
- 分散式服務呼叫鏈追蹤分散式
- go-kit微服務:服務註冊與發現Go微服務
- go-kit微服務:服務熔斷Go微服務
- spring cloud構建網際網路分散式微服務雲平臺-服務鏈路追蹤SpringCloud分散式微服務
- Zipkin — 微服務鏈路跟蹤.微服務
- Jaeger Client Go 鏈路追蹤|入門詳解clientGo
- SpringCloud分散式微服務雲架構第九篇: 服務鏈路追蹤(Finchley版本)SpringGCCloud分散式微服務架構
- 全鏈路追蹤!微服務運維人員終於解放了微服務運維
- Jaeger鏈路追蹤在專案中的應用
- Go微服務框架go-kratos實戰05:分散式鏈路追蹤 OpenTelemetry 使用Go微服務框架分散式
- go-kit 微服務實踐Go微服務
- Spring Cloud實戰系列(七) - 服務鏈路追蹤Spring Cloud SleuthSpringCloud
- 基於OpenTelemetry實現Java微服務呼叫鏈跟蹤Java微服務
- 帶你十天輕鬆搞定 Go 微服務系列(九、鏈路追蹤)Go微服務
- 企業級 SpringCloud 教程 - 服務鏈路追蹤(Spring Cloud Sleuth)SpringGCCloud
- go-kit微服務:限流Go微服務
- Go - 實現專案內鏈路追蹤Go
- 「Java分享客棧」隨時用隨時翻:微服務鏈路追蹤之zipkin搭建Java微服務
- go-kit 微服務 限流 (uber/ratelimit 和 golang/rate 實現)微服務MITGolang
- 萬字詳解!搜狐智慧媒體基於 Zipkin 和 StarRocks 的微服務鏈路追蹤實踐微服務
- 微服務追蹤SQL(支援Isto管控下的gorm查詢追蹤)微服務SQLGoORM
- go-kit微服務:HTTP RESTGo微服務HTTPREST
- Go - 實現專案內鏈路追蹤(二)Go