摘要: 分佈式系統的運維挑戰 容器、Serverless 編程方式的誕生極大提高了軟件交付與部署的效率。在架構的演化過程當中,能夠看到兩個變化: 應用架構開始從單體系統逐步轉變爲微服務,其中的業務邏輯隨之而來就會變成微服務之間的調用與請求。
分佈式系統的運維挑戰
容器、Serverless 編程方式的誕生極大提高了軟件交付與部署的效率。在架構的演化過程當中,能夠看到兩個變化:
- 應用架構開始從單體系統逐步轉變爲微服務,其中的業務邏輯隨之而來就會變成微服務之間的調用與請求。
- 資源角度來看,傳統服務器這個物理單位也逐漸淡化,變成了看不見摸不到的虛擬資源模式。
從以上兩個變化能夠看到這種彈性、標準化的架構背後,原先運維與診斷的需求也變得愈來愈複雜。爲了應對這種變化趨勢,誕生一系列面向 DevOps 的診斷與分析系統,包括集中式日誌系統(Logging),集中式度量系統(Metrics)和分佈式追蹤系統(Tracing)。
Logging,Metrics 和 Tracing
Logging,Metrics 和 Tracing 有各自專一的部分。
- Logging - 用於記錄離散的事件。例如,應用程序的調試信息或錯誤信息。它是咱們診斷問題的依據。
- Metrics - 用於記錄可聚合的數據。例如,隊列的當前深度可被定義爲一個度量值,在元素入隊或出隊時被更新;HTTP 請求個數可被定義爲一個計數器,新請求到來時進行累加。
- Tracing - 用於記錄請求範圍內的信息。例如,一次遠程方法調用的執行過程和耗時。它是咱們排查系統性能問題的利器。
這三者也有相互重疊的部分,以下圖所示。
經過上述信息,咱們能夠對已有系統進行分類。例如,Zipkin 專一於 tracing 領域;Prometheus 開始專一於 metrics,隨着時間推移可能會集成更多的 tracing 功能,但不太可能深刻 logging 領域; ELK,阿里雲日誌服務這樣的系統開始專一於 logging 領域,但同時也不斷地集成其餘領域的特性到系統中來,正向上圖中的圓心靠近。
Tracing 的誕生
- Dapper(Google) : 各 tracer 的基礎
- StackDriver Trace (Google)
- Zipkin(twitter)
- Appdash(golang)
- 鷹眼(taobao)
- 諦聽(盤古,阿里云云產品使用的Trace系統)
- 雲圖(螞蟻Trace系統)
- sTrace(神馬)
- X-ray(aws)
分佈式追蹤系統發展很快,種類繁多,但核心步驟通常有三個:代碼埋點,數據存儲、查詢展現。
下圖是一個分佈式調用的例子,客戶端發起請求,請求首先到達負載均衡器,接着通過認證服務,計費服務,而後請求資源,最後返回結果。
數據被採集存儲後,分佈式追蹤系統通常會選擇使用包含時間軸的時序圖來呈現這個 Trace。
但在數據採集過程當中,因爲須要侵入用戶代碼,而且不一樣系統的 API 並不兼容,這就致使了若是您但願切換追蹤系統,每每會帶來較大改動。
OpenTracing
OpenTracing 是一個輕量級的標準化層,它位於應用程序/類庫和追蹤或日誌分析程序之間。
+-------------+ +---------+ +----------+ +------------+ | Application | | Library | | OSS | | RPC/IPC | | Code | | Code | | Services | | Frameworks | +-------------+ +---------+ +----------+ +------------+ | | | | | | | | v v v v +------------------------------------------------------+ | OpenTracing | +------------------------------------------------------+ | | | | | | | | v v v v +-----------+ +-------------+ +-------------+ +-----------+ | Tracing | | Logging | | Metrics | | Tracing | | System A | | Framework B | | Framework C | | System D | +-----------+ +-------------+ +-------------+ +-----------+
OpenTracing 的優點
- OpenTracing 已進入 CNCF,正在爲全球的分佈式追蹤,提供統一的概念和數據標準。
- OpenTracing 經過提供平臺無關、廠商無關的 API,使得開發人員可以方便的添加(或更換)追蹤系統的實現。
OpenTracing 數據模型
OpenTracing 中的 Trace(調用鏈)經過歸屬於此調用鏈的 Span 來隱性的定義。
特別說明,一條 Trace(調用鏈)能夠被認爲是一個由多個 Span 組成的有向無環圖(DAG圖),Span 與 Span 的關係被命名爲 References。
例如:下面的示例 Trace 就是由8個 Span 組成:
單個 Trace 中,span 間的因果關係 [Span A] ←←←(the root span) | +------+------+ | | [Span B] [Span C] ←←←(Span C 是 Span A 的孩子節點, ChildOf) | | [Span D] +---+-------+ | | [Span E] [Span F] >>> [Span G] >>> [Span H] ↑ ↑ ↑ (Span G 在 Span F 後被調用, FollowsFrom)
有些時候,使用下面這種,基於時間軸的時序圖能夠更好的展示 Trace(調用鏈):
單個 Trace 中,span 間的時間關係 ––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time [Span A···················································] [Span B··············································] [Span D··········································] [Span C········································] [Span E·······] [Span F··] [Span G··] [Span H··]
每一個 Span 包含如下的狀態:(譯者注:因爲這些狀態會反映在 OpenTracing API 中,因此會保留部分英文說明)
- An operation name,操做名稱
- A start timestamp,起始時間
- A finish timestamp,結束時間
- Span Tag,一組鍵值對構成的 Span 標籤集合。鍵值對中,鍵必須爲 string,值能夠是字符串,布爾,或者數字類型。
- Span Log,一組 span 的日誌集合。
每次 log 操做包含一個鍵值對,以及一個時間戳。
鍵值對中,鍵必須爲 string,值能夠是任意類型。
可是須要注意,不是全部的支持 OpenTracing 的 Tracer,都須要支持全部的值類型。
- SpanContext,Span 上下文對象 (下面會詳細說明)
- References(Span間關係),相關的零個或者多個 Span(Span 間經過 SpanContext 創建這種關係)
每個 SpanContext 包含如下狀態:
- 任何一個 OpenTracing 的實現,都須要將當前調用鏈的狀態(例如:trace 和 span 的 id),依賴一個獨特的 Span 去跨進程邊界傳輸
- Baggage Items,Trace 的隨行數據,是一個鍵值對集合,它存在於 trace 中,也須要跨進程邊界傳輸
OpenTracing 實現
Jaeger
Jaeger 是 Uber 推出的一款開源分佈式追蹤系統,兼容 OpenTracing API。
Jaeger 架構
如上圖所示,Jaeger 主要由如下幾部分組成。
- Jaeger Client - 爲不一樣語言實現了符合 OpenTracing 標準的 SDK。應用程序經過 API 寫入數據,client library 把 trace 信息按照應用程序指定的採樣策略傳遞給 jaeger-agent。
- Agent - 它是一個監聽在 UDP 端口上接收 span 數據的網絡守護進程,它會將數據批量發送給 collector。它被設計成一個基礎組件,部署到全部的宿主機上。Agent 將 client library 和 collector 解耦,爲 client library 屏蔽了路由和發現 collector 的細節。
- Collector - 接收 jaeger-agent 發送來的數據,而後將數據寫入後端存儲。Collector 被設計成無狀態的組件,所以您能夠同時運行任意數量的 jaeger-collector。
- Data Store - 後端存儲被設計成一個可插拔的組件,支持將數據寫入 cassandra、elastic search。
- Query - 接收查詢請求,而後從後端存儲系統中檢索 trace 並經過 UI 進行展現。Query 是無狀態的,您能夠啓動多個實例,把它們部署在 nginx 這樣的負載均衡器後面。
Jaeger 存在的問題
- 須要架設並維護存儲。
- UI比較薄弱,有一些個性化的分析需求沒法快速知足(例如對比,統計延遲分佈等)。
Jaeger on Aliyun Log Service
優點
- 原生 Jaeger 僅支持將數據持久化到 cassandra 和 elasticsearch 中,用戶須要自行維護後端存儲系統的穩定性,調節存儲容量。Jaeger on Aliyun Log Service 藉助阿里雲日誌服務的海量數據處理能力,讓您享受 Jaeger 在分佈式追蹤領域給您帶來便捷的同時無需過多關注後端存儲系統的問題。
- Jaeger UI 部分僅提供查詢、展現 trace 的功能,對分析問題、排查問題支持不足。使用 Jaeger on Aliyun Log Service,您能夠藉助日誌服務強大的查詢分析能力,助您更快分析出系統中存在的問題。
- 相對於 Jaeger 使用 elasticsearch 做爲後端存儲,使用日誌服務的好處是支持按量付費,成本僅爲 elasticsearch 的13%。參閱自建ELK vs 日誌服務(SLS)全方位對比
配置步驟
使用實例
HotROD 是由多個微服務組成的應用程序,它使用了 OpenTracing API 記錄 trace 信息。
下面經過一段視頻向您展現如何使用 Jaeger on Aliyun Log Service 診斷 HotROD 出現的問題。視頻包含如下內容:
- 如何配置日誌服務
- 如何經過 docker-compose 運行 Jaeger
- 如何運行 HotROD
- 經過 Jaeger UI 如何檢索特定的 trace
- 經過 Jaeger UI 如何查看 trace 的詳細信息
- 經過 Jaeger UI 如何定位應用的性能瓶頸
- 經過日誌服務管理控制檯,如何定位應用的性能瓶頸
- 應用程序如何使用 OpenTracing API
參考資料
特別感謝
Jaeger on Aliyun Log Service 是基於阿里雲MVP
@WPH95 在業餘時間工做整理而成,感謝 MVP
的傑出貢獻!
識別如下二維碼,閱讀更多幹貨