天天看點

分布式鍊路追蹤技術:監控資料從何而來?

作者:一個即将退役的碼農

我們在日常開發過程中無時無刻不在和資料打交道,想要讓程式運作得穩定順暢就要實時對資料進行觀測。今天我們先來講解觀測的資料到底從哪裡來的?

監控資料來源

我們一般講的資料觀測,其實觀測的就是從發起請求,到真正查詢的這個過程中的資料。那在這個過程中,我們需要關注哪幾個層次的資料呢?接下來,我會從資料請求發起的使用者端到資料查詢響應的服務端逐層分析。

端上通路

首先是使用者側的端上通路,這應該是最容易了解的。在網際網路發展的早期,我們通過 PC 浏覽網頁,就屬于端上通路的範疇。随着移動網際網路的發展,端上通路的範圍得以擴大。我們打開各種 App,或是通路 App 中的小程式/H5 頁面,都屬于端上通路。使用者通過端上通路,也最能直覺地感受到我們程式的響應速度,是以端上通路的資料就變得十分重要。

我們一般可以通過以下幾個方式擷取端上通路的資料:

  1. 使用者體驗監控:Web 頁面中的白屏時間、DOM 元素/資源加載耗時、文檔網絡耗時;App 的卡頓率、崩潰率、熱啟動加載時長等。
  2. 日志:在 Web 頁面中,如果出現腳本錯誤,則需要将相應的異常資訊通過日志的方式上報伺服器;App 也會有相應的日志輸出,但移動端更關注系統崩潰或出現異常時的日志資訊。
  3. 端到端:指的是使用者端(Web/App)到後端伺服器的請求情況,比如通路量、成功率、響應時間等。通過端到端觀測時,我們還需要了解端上所處的地區、網絡環境、響應狀态碼等資訊,才能更好地掌握使用者真實的使用情況。
  4. 可用率:因營運商和地區的不同,會導緻通路端上時有一些差異,比如通路是否可用、響應耗時長短等。這與 CDN、DNS 等公共資源有莫大的關系。

應用程式

當端上發起請求後,一般會到達應用程式。這裡是代碼運作,以及處理使用者請求的地方。在應用程式中,我們可能會內建各種第三方元件,比如常見的 Kafka、Redis、MySQL。應用程式的執行效率最終會通過端上響應情況反映出來,直接影響到使用者的使用體驗。

如果我們想要提升程式的響應速度,就不得不關注以下幾個名額:

  1. 執行情況:我們常說的響應時間、QPS 等,都可以反映應用程式的執行情況。針對端上的請求,或者我們的定時任務,應用程式的執行情況就十分關鍵。執行情況越差,使用者的直覺體驗也會越差。在元件級别,像 MySQL 中的慢查詢監控,Kafka 中的 Lag 監控等,也可以反映應用程式的執行情況。
  2. 資源消耗:應用程式部署後,會消耗一定的資源,例如記憶體級别的 Redis 會消耗大量的記憶體,Kakfa 則因為要進行磁盤寫入是以會要求較好的 I/O。我們的應用程式會區分 I/O 密集型和 CPU 密集型,它們所對應的資源消耗是不同的。
  3. VM 名額監控:指的是 JVM 監控,比如 GC 時間、線程數、FGC/YGC 耗時等資訊。當然,其他語言也有其獨特的統計名額資訊。
  4. 容量:指單個系統可最大承受的容量。容量也是一個非常重要的名額,當應用通路量到達門檻值時,我們一般會對這個應用的通路容量進行擴縮容。
  5. 服務關系:随着分布式系統架構的流行,我們在監控單體應用的基礎上,還必須考慮應用之間的調用關系和調用速度,比如是否會存在兩個服務之間的互相循環引用,下遊服務出現問題是否會幹擾整個流程的執行,又或是服務之間的響應時長、上下遊服務的依賴程度等。
  6. 應用日志:應用日志應該是我們再熟悉不過的内容了。我們開發的應用程式,會記錄下自身的日志,第三方元件也會有相應的日志,比如 MySQL 的程序日志、慢查詢日志等。充分利用應用日志,可以大幅提高我們的排錯能力。
  7. 健康情況:目前服務是否存活、服務運作是否穩定等,這也是十分關鍵的名額。我們在 ES 中可以看到服務的狀态(RED、YELLOW、GREEN)。

業務監控

業務監控也是可觀測系統中一個重要的内容,如果你隻是讓應用程式穩定運作那肯定是遠遠不夠的。是以,我們常常會對具體業務産生的資料進行監控,例如網站系統中我們會關注 PV、UV 等參數;在支付系統中,我們則會關注建立訂單量、成單量等。

業務名額能很好地展現出系統是否穩定。任何系統,如果出現了問題,最先受到影響的肯定是業務名額。當然,如果影響不是特别大,那就說明對這個名額進行監控的意義也不是很大。

業務名額也可以衡量上線後的成效。如果我們需要通過 A/B Test 了解使用者更偏好哪一種模式,可以分别觀察兩種模式下的業務名額來比對使用者喜好。再或者,我們可以通過業務名額得出的結論,在上線前進行一些改進(例如選擇使用者更偏好的模式)來提高成單率。

核心業務名額的設定因具體的業務和場景而異,是以開發人員也需要對業務和代碼有一定的了解。

基礎設施

基礎監控我想你也不陌生。我們的應用程式/元件一般都是運作在雲主機、作業系統上的,如果基礎設施出現了嚴重問題,會影響到雲主機和作業系統,進而牽連應用程式/元件的正常運作。

為了避免這種情況,我們會對基礎設施進行監控,以保證它們可以良好地運作着。

我們一般會從 2 個方向監控:

  1. 資源利用:這個很好了解,像 I/O 使用率、CPU 使用率、記憶體使用率、磁盤使用率、網絡使用率、負載等都屬于資源利用的範疇。
  2. 通信情況:這裡是指主機與主機之間的網絡情況。通信是網際網路中最重要的基石之一,如果兩台主機之間出現如網絡延遲時間大、丢包率高這樣的網絡問題,會導緻業務受阻。

可觀測性核心概念

基于上面幾個層次的資料來源的介紹,你應該對要觀測的資料有了一個大概的了解。

為了解決我在“開篇詞”中提到的 3 個問題,我們通常會通過幾個次元來觀測這些資料,這也是我接下來要為你介紹的可觀測性中比較關鍵的概念:日志、統計名額和鍊路跟蹤。

分布式鍊路追蹤技術:監控資料從何而來?

日志(Logging)

日志是系統中的常見功能,我們前面說的資料來源的各個部分都有可能産生日志。日志一般的描述是:在特定時間發生的事件,被以結構化的形式記錄并産生的文本資料。

日志可以為我們展現系統在任意時間的運作狀态,又因為它是結構化的文本,是以我們很容易通過某種格式來進行檢索,比如下圖就是對 7 月 24 日使用者支付下單操作的記錄:

分布式鍊路追蹤技術:監控資料從何而來?

由于日志是最容易生成的,如果它大量地輸出,會占據比較大的存儲空間,進而影響整個應用程式的性能,比如 Java 中 logback 的日志架構,就算使用了異步線程來執行,也會對磁盤和 I/O 的使用率造成影響。

當然,也有一部分系統是利用日志可追溯、結構化的特點,來實作相關功能的,比如我們最常見的 WAL(Write-Ahead Logging)。WAL 就是在操作之前先進行日志寫入,再執行操作;如果沒有執行操作,那麼在下次啟動時就可以通過日志中結構化的,有時間标記的資訊恢複操作,其中最典型的就是 MySQL 中的 Redo log。

統計名額(Metrics)

統計名額也是我們經常使用的。它是一種可累加的聚合的數值結果,具有原子性。是以,我們可以通過各種數學計算方式來擷取一段時間内的數值。

分布式鍊路追蹤技術:監控資料從何而來?

統計名額針對資料的存儲、處理、壓縮和檢索進行了優化,是以一般可以長期存儲并以很簡單的方式(聚合)查詢。但由于涉及資料的處理(數學計算方式)和壓縮,是以它也會占用一定的 CPU 資源。

統計名額是一個壓縮後的數值,是以如果名額出現異常,我們很難得知是什麼原因導緻的異常。此外,如果我們使用了一個高基數的名額來作為統計的次元,那麼統計就很容易給機器帶來高性能損耗,比如,在基于使用者 ID 的次元去做資料統計時,因為在統計的時候需要一段時間範圍,如果資料過多就必然會造成記憶體上的占用。

講到這裡,你應該對名額有了一定的認識。我們後端經常說的 QPS、TPS、SLA 都是計算後得到的名額;基礎設施中的 CPU 使用率、負載情況也可以認為是名額。

鍊路追蹤(Tracing)

鍊路追蹤 可能是一個較新的概念,但是“全鍊路壓測”這個詞你一定不陌生。鍊路追蹤中的“鍊路”和全鍊路壓測中的“鍊路”,它們的概念是一樣的,隻不過鍊路追蹤是将鍊路的完整行為資訊進行記錄,然後通過可視化的形式展現出來。這裡我用一張圖來說明:

分布式鍊路追蹤技術:監控資料從何而來?

假設我們程式中的一個接口總共有 4 個服務參與,調用的關系分别是 A->B->C->D,其中 B 服務還與 Redis 這種第三方應用産生了調用/請求關系。這一過程,我們就可以在鍊路追蹤中,通過類似于上面這張圖的形式來展示。當然,這隻是個例子,在實際中,鍊路追蹤展示的圖會比這個更加清楚。我會在後面的課程中更加詳細地講解,這裡就不加贅述了。

鍊路是支援跨應用的,比如我們常見的 RPC 請求,就可以說是鍊路中的一部分。

與日志一樣,鍊路追蹤也會造成一定的性能損耗,因為任何形式的觀測都需要存儲一定的資料和時間資訊,這必然會占用一定的 CPU 和記憶體資源。我們一般可以通過采樣的方式解決資源占用的問題,我會在後面“鍊路追蹤”章節中介紹。

鍊路追蹤是整個可觀測性中一個很有趣,也是很重要的部分。希望通過這個簡單的說明,能讓你對它有一個基礎的認識。

三者之間關系

我們一般可以将資料的來源分為 2 個級别:

  1. 請求級别: 資料來源于真實的請求,比如一次 HTTP 調用,RPC 調用;
  2. 聚合級别: 真實的請求名額,或是系統的一些參數資料聚合,比如 QPS、CPU 數值。

根據這 2 個級别,我們可以對上面的 3 個内容加以細化,其中鍊路追蹤是請求級别,因為它和每個請求都挂鈎;日志和統計名額可以是請求級别,也可以是聚合級别,因為它們可能是真實的請求,也可能是系統在對自身診斷時記錄下來的資訊。

那麼當它們兩兩組合之後又是什麼關系呢?我們可以從下圖中看到:

分布式鍊路追蹤技術:監控資料從何而來?
  1. 鍊路追蹤+統計名額(Request-scoped metrics),請求級别的統計:在鍊路追蹤的基礎上,與相關的統計資料結合,進而得知資料與資料、應用與應用之間的關系。
  2. 鍊路追蹤+日志(Request-scoped events),請求級别的事件:這是鍊路中一個比較常見的組合模式。日志本身是每一條單獨存在的,将鍊路追蹤收集到的資訊內建在日志中,可以讓日志之間具備關聯性,使其具有除了事件次元以外的另一個新的次元,上下文資訊。
  3. 日志+統計名額(Aggregatable events),聚合級别的事件:這是在日志中的比較常見的組合。通過解析這部分具有統計名額的資訊,我們可以擷取相關的名額資料。
  4. 三者結合(Request-scoped,aggregatable events):三者結合可以了解為請求級别+聚合級别的事件,由此就形成了一個豐富的、全局的觀測體系。

根據以上這 3 個概念,我們再來想想它們最終會輸出的資料量(Volume)。

統計名額是數值的形式,同時又可以壓縮,是以它所需的存儲量是最小的;日志的輸出量最大,但相對的,它也有比較全的内容記錄;鍊路追蹤則正好處于二者之間,它不會像日志一樣大量地輸出,也不像統計名額一樣節能。

于是,這三者的關系就形成了我們圖中最左側的豎線。

繼續閱讀