go微服務框架Kratos筆記(六)鏈路追蹤實戰


什么是鏈路追蹤

借用阿里雲鏈路追蹤文檔來解釋
分布式鏈路追蹤(Distributed Tracing),也叫 分布式鏈路跟蹤,分布式跟蹤,分布式追蹤 等等,它為分布式應用的開發者提供了完整的調用鏈路還原、調用請求量統計、鏈路拓撲、應用依賴分析等工具,可以幫助開發者快速分析和診斷分布式應用架構下的性能瓶頸,提高微服務時代下的開發診斷效率。
為了應對各種復雜的業務,開發工程師開始采用敏捷開發、持續集成等開發方式。系統架構也從單機大型軟件演化成微服務架構。微服務構建在不同的軟件集上,這些軟件模塊可能是由不同團隊開發的,可能使用不同的編程語言來實現,還可能發布在多台服務器上。因此,如果一個服務出現問題,可能導致幾十個應用都出現服務異常。

分布式追蹤系統可以記錄請求范圍內的信息,例如一次遠程方法調用的執行過程和耗時,是我們排查系統問題和系統性能的重要工具。

調用鏈

在廣義上,一個調用鏈代表一個事務或者流程在(分布式)系統中的執行過程。在OpenTracing標准中,調用鏈是多個Span組成的一個有向無環圖(Directed Acyclic Graph,簡稱DAG),每一個Span代表調用鏈中被命名並計時的連續性執行片段。
下圖是一個分布式調用的例子:客戶端發起請求,請求首先到達負載均衡器,接着經過認證服務、計費服務,然后請求資源,最后返回結果。
圖 1. 分布式調用示例
image
數據被采集存儲后,分布式追蹤系統一般會選擇使用包含時間軸的時序圖來呈現這個調用鏈。

圖 2. 包含時間軸的鏈路圖
image

追蹤信息

追蹤信息包含時間戳、事件、方法名(Family+Title)、注釋(TAG/Comment)。
客戶端和服務器上的時間戳來自不同的主機,我們必須考慮到時間偏差,RPC 客戶端發送一個請求之后,服務器端才能接收到,對於響應也是一樣的(服務器先響應,然后客戶端才能接收到這個響應)。這樣一來,服務器端的 RPC 就有一個時間戳的一個上限和下限。

追蹤采樣

鏈路追蹤在生成追蹤和收集追蹤數據的時候會消耗系統資源,在服務高負載情況下可能會導致系統性能下降,因為在鏈路追蹤上可以參考跟蹤采樣的思路降低鏈路追蹤的消耗。

  1. 固定采樣(1/1024)
    這種采樣方案對於高吞吐高負載的線上服務來說相當有用,在大吞吐量的情況下某些事件仍然可能經常出現,並且被采樣到,但是在比較低的負載情況下這種采樣方式往往可能會漏掉某些重要事件,而選擇較高的采樣率就需要接受性能損耗。
  2. 積極采樣
    在低負載情況下固定采樣無法采集到重要數據的情況下,可以采用動態的積極采樣方式,例如在高QPS情況下采樣率下降,低QPS下提高采樣率。

如何使用

目前業界開源的知名鏈路追蹤系統比如Google的Dapper,Twitter的zipkin,淘寶的鷹眼,新浪的Watchman,京東的Hydra等
而本文則使用Jaeger來作為鏈路追蹤系統
簡單用docker起一個jaeger
docker的安裝

docker run -d -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 14269:14269   -p 9411:9411 jaegertracing/all-in-one:latest

訪問127.0.0.1:16686
看到這個頁面就OK了
image

在kratos中植入鏈路追蹤

根據官方文檔kratos 框架提供的自帶中間件中有一個名為 tracing 中間件,它基於 Opentelemetry 實現了kratos 框架的鏈路追蹤功能

  1. 在main.go中構建鏈路追蹤
//構建全鏈路追蹤
// tracerProvider returns an OpenTelemetry TracerProvider configured to use
// the Jaeger exporter that will send spans to the provided url. The returned
// TracerProvider will also use a Resource configured with all the information
// about the application.
func tracerProvider(url string) (*trace.TracerProvider, error) {
	// Create the Jaeger exporter
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
	if err != nil {
		return nil, err
	}
	tp := trace.NewTracerProvider(
		// Always be sure to batch in production.
		trace.WithBatcher(exp),
		// Record information about this application in an Resource.
		trace.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String(Name), //實例名稱
			attribute.String("environment", Name), // 相關環境
			attribute.String("ID", Version),       //版本
		)),
	)
	return tp, nil
}
  1. 在main方法中調用tracerProvider
	//啟動鏈路追蹤,此處需要填寫鏈路追蹤采集地址
	//http://127.0.0.1:14268/api/traces
	tp, err := tracerProvider(config.GetConfig().GetString("jaeger.ipaddr"))
	if err != nil {
		panic(err)
	}
	//將tp作為全局鏈路追蹤的提供程序
	otel.SetTracerProvider(tp)
  1. 在client和server端加上鏈路追蹤中間件
    server端
//grpc
var opts = []grpc.ServerOption{
		grpc.Middleware(
			recovery.Recovery(),
			logging.Server(logger), //日志中間件
			tracing.Server(),       //鏈路追蹤中間件
		),
	}
//http
	var opts = []http.ServerOption{
		http.Middleware(
			recovery.Recovery(),
			logging.Server(logger), //日志中間件
			tracing.Server(),       //鏈路追蹤中間件
		),
	}

client端

	grpc.WithMiddleware(
			recovery.Recovery(),
			logging.Client(logger), //日志中間件,
			tracing.Client(),       //鏈路追蹤中間件
		),

啟動server端和client端,訪問一下接口
可以發現jaeger上成功監測到請求鏈路
image
拓撲圖也成功展示出來
image

References

https://go-kratos.dev/blog/go-kratos-opentelemetry-practice
https://www.jianshu.com/p/07cf4093536a?from=singlemessage
https://help.aliyun.com/document_detail/90277.html?spm=5176.22294701.J_5253785160.4.49451088XuirYu
如有錯誤請留言反饋


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM