簡介
jaeger是一個比較有名的分布式鏈路追蹤系統,底層用golang實現,兼容opentracing標准。
部署
我們用docker部署,集成整套環境,docker地址:https://hub.docker.com/r/jaegertracing/all-in-one
直接運行docker命令安裝:
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 9411:9411 \
jaegertracing/all-in-one:latest
執行完成后,用
命令:docker ps
看看運行起來沒,這里看結果已經運行了:
訪問jaeger的web界面:
localhost:16686
如果你是遠程,這里的localhost可以換成你的服務器ip,或者你配置的域名。
簡單demo
先編寫一個初始化jaeger tracer的initJaeger方法:
此時我們要在reporter中配置jaeger Agent的ip與端口,以便將tracer的信息發布到agent中。配置LocalAgentHostPort參數為127.0.0.1:6381,6381接口是接受壓縮格式的thrift協議數據。如果是遠程這里的 127.0.0.1 可以設置為你遠程ip地址。
采樣率暫且設置為1
func initJaeger(service string) (opentracing.Tracer, io.Closer) {
cfg := &config.Configuration{
Sampler:&config.SamplerConfig{
Type: "const",
Param:1,
},
Reporter: &config.ReporterConfig{
LogSpans: true,
LocalAgentHostPort: "127.0.0.1:6831",
},
}
tracer, closer, err := cfg.New(service, config.Logger(jaeger.StdLogger))
if err != nil {
panic(fmt.Sprintf("Error: connot init Jaeger: %v\n", err))
}
return tracer, closer
}
然后我們在main函數中創建調用InitJaeger,並創建一個root span,調用兩個函數,分別表示調用兩個分布式服務。
我們用ContextWithSpan來創建一個新的ctx,將span的信息與context關聯,傳到TestDemo中時,需要創建一個子span,父span是ctx中的span。
我們在TestDemo中調用StartSpanFromContext時,忽略了第二個參數,這是利用子span創建的新的context,當我們在TestDemo中再調用別的比如TestDemo2時,我們應該使用新的context,而不是傳入的ctx。
注意StartSpanFromContext會用到opentracing.SetGlobalTracer()來啟動新的span,所以在main函數中需要調用。
func TestDemo(req string, ctx context.Context) (reply string) {
// 1. 創建span
span, _ := opentracing.StartSpanFromContext(ctx, "span_testdemo")
defer func() {
// 4. 接口調用完,在tag中設置request和reply
span.SetTag("request", req)
span.SetTag("reply", reply)
span.Finish()
}()
println(req)
//2. 模擬耗時
time.Sleep(time.Second/2)
//3. 返回reply
reply = "TestDemoReply"
return
}
// TestDemo2, 和上面TestDemo 邏輯代碼一樣
func TestDemo2(req string, ctx context.Context) (reply string) {
span, _ := opentracing.StartSpanFromContext(ctx, "span_testdemo2")
defer func() {
span.SetTag("request", req)
span.SetTag("reply", reply)
span.Finish()
}()
println(req)
time.Sleep(time.Second/2)
reply = "TestDemo2Reply"
return
}
func main() {
tracer, closer := initJaeger("jager-test-demo")
defer closer.Close()
opentracing.SetGlobalTracer(tracer)
span := tracer.StartSpan("span_root")
ctx := opentracing.ContextWithSpan(context.Background(), span)
r1 := TestDemo("Hello TestDemo", ctx)
r2 := TestDemo2("Hello TestDemo2", ctx)
fmt.Println(r1, r2)
span.Finish()
}
運行demo:
go run simple/main.go
運行提交的span信息會打印出來:
21:57:30 debug logging disabled
21:57:30 Initializing logging reporter
21:57:30 debug logging disabled
Hello TestDemo
21:57:30 Reporting span 2163520004cced2a:4155a263b5147904:2163520004cced2a:1
Hello TestDemo2
21:57:31 Reporting span 2163520004cced2a:01928bf482621c17:2163520004cced2a:1
TestDemoReply TestDemo2Reply
21:57:31 Reporting span 2163520004cced2a:2163520004cced2a:0000000000000000:1
然后在去jaeger UI上刷新查看,會出現記錄:
可以發現有分層,時間耗時也明顯,接口先后調用也很清晰。
點擊上面的 jager-test-demo 進去,可以看到下面的這種調用情況: