通過Zipkin為應用埋點並上報鏈路資料至Managed Service for OpenTelemetry後,Managed Service for OpenTelemetry即可開始監控應用,您可以查看應用拓撲、調用鏈路、異常事務、慢事務和SQL分析等一系列監控資料。本文介紹如何使用Zipkin為Go應用埋點並上報資料。
為獲得更豐富的功能、更先進的鏈路追蹤能力,以及最佳使用體驗,建議您使用OpenTelemetry協議將應用接入Managed Service for OpenTelemetry。我們為您提供了詳細的OpenTelemetry接入指南和最佳實務,協助您快速上手Managed Service for OpenTelemetry。更多資訊,請參見接入應用。
ARMS應用監控針對Golang語言提供了商業化版本的自研探針,提供了無侵入的埋點能力,擁有更加豐富的功能和更高的穩定性。詳細資料,請參見開始監控Golang應用。
前提條件
背景資訊
Zipkin是一款開源的分布式即時資料追蹤系統(Distributed Tracking System),由Twitter公司開發和貢獻。其主要功能是彙總來自各個異構系統的即時監控資料。
代碼埋點
要通過Zipkin將Go應用資料上報至Managed Service for OpenTelemetry控制台,首先需要完成埋點工作。
添加組件依賴。
[[constraint]] name = "github.com/openzipkin/zipkin-go" version = "0.1.1" [[constraint]] name = "github.com/gorilla/mux" version = "1.6.2"
建立Tracer。Tracer對象可以用來建立Span對象(記錄分布式操作時間)。Tracer對象還配置了上報資料的網關地址、本機IP、採樣頻率等資料,您可以通過調整採樣率來減少因上報資料產生的開銷。
func getTracer(serviceName string, ip string) *zipkin.Tracer { // Create a reporter to be used by the tracer. reporter := httpreporter.NewReporter("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_aokcdqnxyz@123456ff_abcdef123@abcdef123/api/v2/spans") // Configure the local endpoint for the service. endpoint, _ := zipkin.NewEndpoint(serviceName, ip) // Configure the sampling strategy. sampler := zipkin.NewModuloSampler(1) // Initialize the tracer. tracer, _ := zipkin.NewTracer( reporter, zipkin.WithLocalEndpoint(endpoint), zipkin.WithSampler(sampler), ) return tracer; }
記錄請求資料。
// tracer can now be used to create spans. span := tracer.StartSpan("some_operation") // ... do some work ... span.Finish()
說明以上代碼用於記錄請求的根操作,如果需要記錄請求的上一步和下一步操作,則需要傳入上下文。樣本:
childSpan := tracer.StartSpan("some_operation2", zipkin.Parent(span.Context())) // ... do some work ... childSpan.Finish()
可選:為了快速排查問題,您可以為某個記錄添加一些自訂標籤,例如記錄是否發生錯誤、請求的傳回值等;或自訂上報異常等特定資訊。
添加自訂標籤:
childSpan.Tag("http.status_code", statusCode)
自訂上報異常:
childSpan := tracer.StartSpan("some_operation2", zipkin.Parent(span.Context())) // ... do some work ... var events = make(map[string]string) events["event"] = "error" events["stack"] = "Runtime Exception: unable to find userid" jsonStr, err := json.Marshal(events) if err == nil { childSpan.Annotate(time.Now(), string(jsonStr)) } childSpan.Finish()
在分布式系統中發送RPC請求時會帶上Tracing資料,包括TraceId、ParentSpanId、SpanId、Sampled等。您可以在HTTP請求中使用Extract/Inject方法在HTTP Request Headers上透傳資料。總體流程如下:
Client Span Server Span ┌──────────────────┐ ┌──────────────────┐ │ │ │ │ │ TraceContext │ Http Request Headers │ TraceContext │ │ ┌──────────────┐ │ ┌───────────────────┐ │ ┌──────────────┐ │ │ │ TraceId │ │ │ X-B3-TraceId │ │ │ TraceId │ │ │ │ │ │ │ │ │ │ │ │ │ │ ParentSpanId │ │ Inject │ X-B3-ParentSpanId │Extract │ │ ParentSpanId │ │ │ │ ├─┼─────────>│ ├────────┼>│ │ │ │ │ SpanId │ │ │ X-B3-SpanId │ │ │ SpanId │ │ │ │ │ │ │ │ │ │ │ │ │ │ Sampled │ │ │ X-B3-Sampled │ │ │ Sampled │ │ │ └──────────────┘ │ └───────────────────┘ │ └──────────────┘ │ │ │ │ │ └──────────────────┘ └──────────────────┘
說明目前Zipkin已有組件支援以HTTP、gRPC這兩種RPC協議透傳Context資訊。
在用戶端調用Inject方法傳入Context資訊。
req, _ := http.NewRequest("GET", "/", nil) // configure a function that injects a trace context into a request injector := b3.InjectHTTP(req) injector(sp.Context())
在服務端調用Extract方法解析Context資訊。
req, _ := http.NewRequest("GET", "/", nil) b3.InjectHTTP(req)(sp.Context()) b.ResetTimer() _ = b3.ExtractHTTP(copyRequest(req))
快速入門
接下來以一個樣本示範如何通過Zipkin上報Go應用資料。
常見問題
問:為什麼按照快速入門的步驟操作沒有上報資料?
答:請檢查運行過程中是否有提示,並檢查endpoint_url的配置是否正確。例如,錯誤failed the request with status code 403
表明使用者名稱或密碼不正確。