1. 程式人生 > 其它 >Go微服務架構實戰 下篇:1. gRPC + Opentracing + Zipkin實現分散式鏈路追蹤系統

Go微服務架構實戰 下篇:1. gRPC + Opentracing + Zipkin實現分散式鏈路追蹤系統

Go微服務架構實戰-【公粽號:堆疊future】

原文
Go微服務架構實戰目錄

1. 微服務架構上篇

1. grpc技術介紹

2. grpc+protobuf+閘道器實戰

3. etcd技術介紹

4. 基於etcd的服務發現與註冊

5. 基於etcd的分散式鎖實戰

2. 微服務架構中篇

1. k8s架構介紹

2. 基於k8s的容器化部署

3. 基於k8s的Deployment工作負載

4. 基於k8s的ingress實戰

5. 基於ingress和service實現灰度釋出

6. 常見的服務治理策略

3. 微服務架構下篇

分散式鏈路追蹤實戰

乾貨:


什麼是APM

什麼是Opentracing

什麼是SpanID

什麼是TraceID

基於zipkin構建鏈路追蹤


1. 什麼是APM

APM(Application Performance Management,即應用效能管理,在分散式領域也稱為分散式跟蹤管理)對企業的應用系統進行實時監控,它是用於實現對應用程式效能管理和故障管理的系統化的解決方案。

APM核心功能:

  • 服務呼叫跟蹤

  • 應用系統存活檢測

  • 監控告警

開源APM管理工具:

  • ZipKin

  • PinPoint

  • SkyWalking

  • Prometheus

我們這篇文章主要是講解APM的核心功能之一:服務呼叫跟蹤,用到的工具是ZipKin,本來想用Prometheus

搭建一個監控平臺,想來想去比較簡單,大家直接在本地就可以搭建單機版的監控平臺。

2. 什麼是Opentracing

OpenTracing通過提供平臺無關、廠商無關的API,使得開發人員能夠方便的新增(或更換)追蹤系統的實現。

不過OpenTracing並不是標準。因為CNCF不是官方標準機構,但是它的目標是致力為分散式追蹤建立更標準的API和工具。

3. 什麼是TraceID

一個trace代表了一個事務或者流程在(分散式)系統中的執行過程,而這個過程會有唯一ID去標識,這個唯一ID就是Trace ID,通俗解釋就是一個API請求的完整呼叫流程。

4. 什麼是SpanID

一個span代表在分散式系統中完成的單個工作單元,這個工作單元有唯一ID去標識,這個唯一ID就是Span ID

。也包含其他span的“引用”,這允許將多個spans組合成一個完整的Trace。

通俗解釋就是在Trace這樣一個完整呼叫的流程中,Span扮演的角色就是每次執行的一次IO或者非IO操作。所以你通過Trace找到整個鏈路,然後從鏈路中找到確定的Span,這樣就可以準確定位一次問題或者效能查詢。

5. 其他名稱解釋

Span tags(跨度標籤)可以理解為使用者自定義的Span註釋。便於查詢、過濾和理解跟蹤資料。

Span logs(跨度日誌)可以記錄Span內特定時間或事件的日誌資訊。主要用於捕獲特定Span的日誌資訊以及應用程式本身的其他除錯或資訊輸出。

SpanContext 代表跨越程序邊界,傳遞到子級Span的狀態。常在追蹤示意圖中建立上下文時使用。

6. 案例

圖中可以看到以下內容:

  • 執行時間的上下文

  • 服務間的層次關係

  • 服務間序列或並行呼叫鏈

結合以上資訊,在實際場景中我們可以通過整個系統的呼叫鏈的上下文、效能等指標資訊,一下子就能夠發現系統的痛點在哪兒。

7. 什麼是ZipKin

Zipkin是分散式追蹤系統。它的作用是收集解決微服務架構中的延遲問題所需的時序資料。它管理這些資料的收集和查詢。

Zipkin的設計基於Google Dapper論文。

8. 基於ZipKin構建鏈路追蹤

首先在基於之前的專案之中,把server.go修改一下,讓其支援分散式鏈路追蹤。server.go:

const(
SERVICE_NAME="simple_zipkin_server"
ZIPKIN_HTTP_ENDPOINT="http://127.0.0.1:9411/api/v2/spans"//上報到ZipKin中的鏈路
ZIPKIN_RECORDER_HOST_PORT="0.0.0.0"
)

funcmain(){
...

//鏈路日誌輸出到哪
reporter:=httpreporter.NewReporter(ZIPKIN_HTTP_ENDPOINT)
deferreporter.Close()

//記錄服務名稱和埠
endpoint,err:=zipkin.NewEndpoint(SERVICE_NAME,ZIPKIN_RECORDER_HOST_PORT)
iferr!=nil{
log.Fatalf("zipkin.NewEndpointerr:%v",err)
}

tracer,err:=zipkin.NewTracer(reporter,zipkin.WithLocalEndpoint(endpoint))
iferr!=nil{
log.Fatalf("zipkin.NewTracererr:%v",err)
}

//接入opentracing
t:=zipkinot.Wrap(tracer)
opentracing.SetGlobalTracer(t)

logrus.Infof("startinghelloserviceat:%s",*port)

//初始化grpcserver,並註冊中介軟體
s:=grpc.NewServer(
//otgrpc.LogPayloads是否記錄入參和出參
//otgrpc.SpanDecorator裝飾器,回撥函式
//otgrpc.IncludingSpans是否記錄
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(otgrpc.OpenTracingServerInterceptor(t,
otgrpc.LogPayloads(),
//IncludingSpans是請求前回調
otgrpc.IncludingSpans(func(parentSpanCtxopentracing.SpanContext,methodstring,req,respinterface{})bool{
log.Printf("method:%s",method)
log.Printf("req:%+v",req)
log.Printf("resp:%+v",resp)
returntrue
}),
//SpanDecorator是請求後回撥
otgrpc.SpanDecorator(func(span opentracing.Span,methodstring,req,respinterface{},grpcErrorerror){
log.Printf("method:%s",method)
log.Printf("req:%+v",req)
log.Printf("resp:%+v",resp)
log.Printf("grpcError:%+v",grpcError)
}),
))),
)

//註冊服務
pb.RegisterGreeterServer(s,&server{})
fmt.Println("ddd")
s.Serve(lis)
}

至此我們的grpc服務就有了鏈路追蹤功能,接下來我們演示下,啟動server.go:k8s-grpc-demo go run cmd/svr/svr.go -port 50004

然後啟動客戶端:k8s-grpc-demo go run cmd/cli/cli.go

我們可以看下server.go的日誌:我們發現日誌完美記錄到ZipKin中,接下來我們看下ZipKin地址:當我們點選RUN QUERY的時候可以看到如下:當我們點選某一個Trace的時候,就進入這個Trace的整個呼叫鏈路詳情中:

這樣我就基於gRPC + Opentracing + Zipkin的分散式鏈路追蹤系統就搭建完成了,大家下去可以自己嘗試下。

9. 小結

各位讀者朋友們,我們的Go微服務架構實戰【上中下】系列課程到這裡就基本上結束了,寫作過程中雖然很累,很艱辛,但是這個系列能在有限的業餘時間堅持創作完實屬不易,希望在之後的業餘時間當中能繼續為大家帶來更棒的系列課程,歡迎大家點贊、關注和分享。

最後再次感謝大家對本系列課程的大力支援,由於個人能力有限,難免哪裡寫的有問題歡迎大家指出,也歡迎各位能在百忙之中抽出時間學習,最後和各位分享一句話:簡單的東西不一定是最好的,但最好的東西一定是簡單的。

公粽號:堆疊future

使很多處於迷茫階段的coder能從這裡找到光明,堆疊創世,功在當代,利在千秋