分布式链路追踪实践(三)

HTTP 和 gRPC 分布式链路追踪 SDK

Posted by ethan.luo on December 5, 2020

Go Tracing SDK

快速开始

启动 Jaeger or Zipkin

debug 调试启动本地 Jaeger

docker run \
-p 5775:5775/udp \
-p 16686:16686 \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 14268:14268 \
jaegertracing/all-in-one:latest

打开 lens 在 istio-system 中找到 jaeger, 点击 “query: 16686/TCP” 在浏览器即可打开 web ui 。

引入 SDK 包

HTTP 请求链路

在 http request 方法侧创建 trace

代码如下:

  • client 端
import (
    tracing "github.com/traceandtrace-go/wrapper/http"
)

_, cancel := tracing.AddTracing(r, tags)
defer cancel()

//或者 添加自定义 serviceName 
_, cancel := tracing.AddTracing(r, tags, map[string]string{"serviceName":"your svc name", "traceType":"Jaeger or Zipkin"})
defer cancel()

...
  • server 端
import (
    tracing "github.com/traceandtrace-go/wrapper/http"
)

pctx, cancel := tracing.AddTracing(r, tags)
defer cancel()
//添加 header
r.Header = header
//或者 添加自定义 serviceName
pctx, cancel := tracing.AddTracing(r, tags, map[string]string{"serviceName":"your svc name", "traceType":"Jaeger or Zipkin"})
defer cancel()

//pctx 为从根 context 创建子协程会话, 在使用 RPC 请求时将此会话传入
//可以实现 http 到 rpc span 的传递 
RpcRequestMethod(pctx)

...

tags 为 map[string]string 类型, 可以传递 logs k-v, tag 和 field

RPC 请求链路

在 rpc request 方法侧创建 trace

  • client 端
import (
    tracing "github.com/traceandtrace-go/wrapper/rpc"
)

//创建 rpc options
rpcOption, closer, _ := tracing.AddTracing(serviceName)
defer closer.Close()

//dial
conn, err := grpc.Dial(addr, grpc.WithInsecure(), rpcOption)
if err != nil {
}
...
  • server 端
import (
    tracing "github.com/traceandtrace-go/wrapper/rpc"
)

//不需要请求别的 rpc 服务
rpcOption, closer, _ := rpcTracing.AddRpcServerTracing(serviceName)
defer closer.Close()

//在 server 端监听进程中加入 rpcOptions 即可
s := grpc.NewServer(rpcOption)

//------------------------------------------------

//需要请求别的 rpc 服务
rpcOption, closer, tracer := rpcTracing.AddRpcServerTracing(serviceName)
defer closer.Close()

//在 server 端监听进程中加入 rpcOptions 即可
s := grpc.NewServer(rpcOption)
//rpc 请求
newRpcServiceReq(tracer)

...

并发处理

协程 context 管理

  • 通过 context.Background() 创建子协程 context, 形成会话树 (协程树), 是线程安全的 (不存在数据竞争问题) ;
  • 通过 context WithCancel() 创建子协程会话, 管理协程任务 ;
  • 每个 context 会携带父类 trace 和 子 span 的相关 data

goroutine 会话

协程 trace job 管理和资源回收

启动和暂停 trace job

//启动协程 job
ch := make(chan context.Context, 0)
go doTask(ch, ctx, r, svc, traceType, tags)

//任务结束 (接受信号)
pctx := <-ch
pch <- pctx

//资源回收 (暂停任务)
for {
    select {
        case <-ctx.Done():
            cancel()
            return
        default:
            break
    }
}