概述
首先同步下專案概況:
上篇文章分享了,路由中介軟體 - 捕獲異常,這篇文章我們們分享:路由中介軟體 - Jaeger 鏈路追蹤。
啥是鏈路追蹤?
我理解鏈路追蹤其實是為微服務架構提供服務的,當一個請求中,請求了多個服務單元,如果請求出現了錯誤或異常,很難去定位是哪個服務出了問題,這時就需要鏈路追蹤。
我們們先看一張圖:
這張圖的呼叫鏈還比較清晰,我們們想象一下,隨著服務的越來越多,服務與服務之間呼叫關係也越來越多,可能就會發展成下圖的情況。
這呼叫關係真的是... 看到這,我的內心是崩潰的。
那麼問題來了,這種情況下怎麼快速定位問題?
如何設計日誌記錄?
我們自己也可以設計一個鏈路追蹤,比如當發生一個請求,我們們記錄它的:
- 請求的唯一標識
- 請求了哪些服務?
- 請求的服務依次順序?
- 請求的 Request 和 Response 日誌?
- 對日誌進行收集、整理,並友好展示
怎麼去實現請求的唯一標識?
以 Go 為例 寫一箇中介軟體,在每次請求的 Header 中包含:X-Request-Id,程式碼如下:
func SetUp() gin.HandlerFunc {
return func(c *gin.Context) {
requestId := c.Request.Header.Get("X-Request-Id")
if requestId == "" {
requestId = util.GenUUID()
}
c.Set("X-Request-Id", requestId)
c.Writer.Header().Set("X-Request-Id", requestId)
c.Next()
}
}
複製程式碼
每個 Request 和 Response 日誌中都要包含 X-Request-Id。
問題又來了,每次呼叫都記錄日誌,當呼叫的服務過多時,頻繁的記錄日誌,就會有效能問題呀,腫麼辦?
哎,這麼麻煩,看看市面上有沒有一些開源工具呢?
開源工具
- Jaeger:www.jaegertracing.io
- Zipkin:zipkin.io/
- Appdash:about.sourcegraph.com/
這個就不多做介紹了,基本上都能滿足需求,至於優缺點,大家可以挨個去瞅瞅,喜歡哪個就用哪個?
我為什麼選擇 Jaeger ?
因為我目前只會用這個,其他還不會 ...
我們們一起看下 Jaeger 是怎麼回事吧。
Jaeger 架構圖
圖片來源於官網。
簡單介紹下上圖三個關鍵元件:
Agent
Agent是一個網路守護程式,監聽通過UDP傳送過來的Span,它會將其批量傳送給collector。按照設計,Agent要被部署到所有主機上,作為基礎設施。Agent將collector和客戶端之間的路由與發現機制抽象了出來。
Collector
Collector從Jaeger Agent接收Trace,並通過一個處理管道對其進行處理。目前的管道會校驗Trace、建立索引、執行轉換並最終進行儲存。儲存是一個可插入的元件,現在支援Cassandra和elasticsearch。
Query
Query服務會從儲存中檢索Trace並通過UI介面進行展現,該UI介面通過React技術實現,其頁面UI如下圖所示,展現了一條Trace的詳細資訊。
其他元件,大家可以瞭解下並選擇性使用。
Jaeger Span
圖片來源於官網。
怎麼操作 Span 呢?Span 有哪些可以呼叫的 API ?
Jaeger 部署
All in one
為了方便大家快速使用,Jaeger 直接提供一個 All in one 包,我們可以直接執行,啟動一套完整的 Jaeger tracing 系統。
啟動成功後,訪問 http://localhost:16686 就可以看到 Jaeger UI。
獨立部署
- jaeger-agent
- jaeger-collector
- jaeger-query
- jaeger-ingester
- jaeger-operator
- jaeger-cassandra-schema
- jaeger-es-index-cleaner
- spark-dependencies
可以自由搭配,組合使用。
Jaeger 埠
-
埠:6831
-
協議:UDP
-
所屬模組:Agent
-
功能:通過相容性 Thrift 協議,接收 Jaeger thrift 型別資料
-
埠:14267
-
協議:HTTP
-
所屬模組:Collector
-
功能:接收客戶端 Jaeger thrift 型別資料
-
埠:16686
-
協議:HTTP
-
所屬模組:Query
-
功能:客戶端前端介面展示埠
Jaeger 取樣率
分散式追蹤系統本身也會造成一定的效能低損耗,如果完整記錄每次請求,對於生產環境可能會有極大的效能損耗,一般需要進行取樣設定。
固定取樣
(sampler.type=const)
- sampler.param=1 全取樣,
- sampler.param=0 不取樣;
按百分比取樣
(sampler.type=probabilistic)
- sampler.param=0.1 則隨機採十分之一的樣本;
取樣速度限制
(sampler.type=ratelimiting)
- sampler.param=2.0 每秒取樣兩個traces;
動態獲取取樣率
(sampler.type=remote)
- 這個是預設配置,可以通過配置從 Agent 中獲取取樣率的動態設定。
Jaeger 缺點
- 接入過程有一定的侵入性;
- 本身缺少監控和報警機制,需要結合第三方工具來實現,比如配合Grafana 和 Prometheus實現;
看到這,說的都是理論,大家的心裡話可能是:
實戰
- Jaeger 部署
- Jaeger 在 Gin 中使用
- Jaeger 在 gRPC 中使用
關於實戰的分享,我準備整理出 4 個服務,然後實現服務與服務之間進行相互呼叫,目前 Demo 還沒寫完...
下篇文章再給大家分享。