天天看點

分布式鍊路追蹤技術:如何通過分析資料快速定位系統隐患?

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

之前的篇章我們了解了統計名額的基本概念。今天我将從使用者側到伺服器,監控名額依次有端上通路、應用程式、元件和機器資訊,讓你更輕松地通過統計資料來了解系統隐患。

端上通路

端上通路一般可以細分為 2 個,App 和網頁。 兩個雖然都屬于端上,但是側重點不一樣,二者之間的差別主要可以是以下 4 點:

  1. 通路方式:這個很好了解,App 需要在應用市場下載下傳使用,下載下傳會花費一定的時間,而網頁隻需要輸入一個位址或直接利用搜尋引擎。
  2. 相容性:從使用者的角度來講,相容性十分關鍵。 App 一般具有很好的相容性,但由于 Android 廠家相對較多,是以每個廠家可能會有一些細微的差别,但是整體的相容性不會有太大問題; 網頁需要考慮各種不同的浏覽器廠商,有些差别還是比較大的,比如最常見的 IE8 相對而言就比較難做相容。
  3. 内容變更:顯示的内容需要變更時,App 往往需要很長的周期,因為需要進行發版、應用稽核、上架,最後才到使用者更新,是以有時為了友善,在 App 内嵌入 H5 也是很常見的; 網頁則是實時的,隻需要開發人員将更改後的内容上線,使用者通路時就會是最新的。
  4. 使用體驗:從使用者使用體驗角度來講,App 往往體驗更好,因為它是手機上的應用,是以包括在使用、消息推送等方面都有更好的支援; 網頁相對來說會差一些,更多的是展示資訊的功能,因為它屬于在浏覽器應用中的内容,是以其權限相對較少。

應用程式

介紹了二者的差別後,我先來講一講如今更為使用者青睐的 App,看看 App 中有哪些比較常見的名額:

  1. 崩潰率:崩潰指的是應用在運作過程中出現強制關閉的現象。 崩潰會打斷了使用者操作的體驗,造成業務中斷。 崩潰率過高還會導緻使用者的留存率下降,品牌口碑變差,等等。
  2. 卡頓率:App 中的卡頓率指的是 UI 重新整理時出現卡頓的情況。 如果卡頓率過高,會讓使用者感覺 App 運作很慢,降低使用者的使用體驗。
  3. 解除安裝率:解除安裝說明使用者很難适應你的産品,解除安裝率可以算是最能檢測使用者在使用一個産品時是否滿意的一個名額了。 解除安裝率的升高可能是各個方面導緻的,比如推送過多打擾到使用者,有嚴重的 bug 影響到使用體驗,等等。

網頁

介紹完 App 後,我再帶你了解一下網頁,網頁會更加關注顯示體驗,是以其中一般會有這樣一些名額:

  1. 白屏時間:指的是使用者通路頁面時,從使用者輸入位址欄之後到首次出現内容的時間,也叫作首次渲染時間。 白屏時間的長短會影響使用者的使用體驗,白屏時間長會導緻使用者認為網站比較慢。 如果出現較長時間的空白,有可能是伺服器響應慢或是網絡波動等原因造成的。
  2. 首屏時間:指的是使用者輸入位址欄之後到首個螢幕渲染完成,即完全顯示了頁面内容的時間。 首屏時間會受資源下載下傳速度影響,首屏渲染的速度越快,使用者的使用體驗也會更好。

通用名額

端上的資源請求,一般都會經曆以下幾個步驟:DNS 尋找,建立與伺服器的連結,發送請求,請求響應。 這幾個步驟是可以被監控起來,現在很多主流的撥測軟體也會提供這樣的統計功能,撥測軟體其實就是利用各個不同地方的機器發起請求,來測試網絡情況。

分布式鍊路追蹤技術:如何通過分析資料快速定位系統隐患?

App 和網頁,在發送請求和擷取資料内容的過程中,除了以上提到的名額,還有以下幾個名額需要注意:

  1. DNS 響應時間:通常用來記錄通路位址向 DNS 伺服器發起請求,到 DNS 傳回伺服器 IP 位址資訊的時間。
  2. 建立連接配接時間:用戶端通過 TCP 與伺服器建立的時間。
  3. SSL 握手時間:SSL 握手指的是與 HTTPS 伺服器端進行建立連結的整個過程,其耗時就是 SSL 握手時間。
  4. 首位元組時間:從用戶端發送請求,到接收伺服器首個位元組的時間。是以,它包含了伺服器的響應耗時資訊。
  5. 下載下傳内容時間:接收到内容後,内容被完整下載下傳完成的時間。

通用名額并不限于 App 或是網頁。通過這些名額,你可以更加了解用戶端從請求發起到接收完整内容的耗時情況。通用名額前 3 項(DNS 響應時間、建立連接配接時間、SSL 握手時間)是基礎功能,在優化時更偏向運維層面;首位元組時間和下載下傳内容時間,則更多的是後端開發人員來優化。

應用程式

介紹完端上通路後,我們再來看看應用程式。對于應用程式,需要監控的名額就更多了,我會分請求、資料處理、元件協作資源、業務名額、VM 監控這 5 個部分來介紹。

業務名額更多是傾向于開發人員在編寫代碼時需要自定義控制的名額内容,這一課時我會略過這一内容的介紹,在“07 | 名額編寫:如何編寫出更加了解系統的名額?”這一課時我會有詳細的講解。

請求

請求指的是端上通過 HTTP 等方式發起的請求,與請求相關的名額有以下幾個需要關注:

  1. QPS:我在“04 | 統計名額:‘五個九’對系統穩定的意義?”這個課時中介紹過,QPS 代表了請求數量,它是我們能最快了解這個系統使用情況的一個名額。
  2. 狀态碼:針對 HTTP(S) 的請求,一般會細化響應狀态碼的數量名額。2xx:響應被正常處理。一般系統中會使用 JSON 來傳回資料,而 JSON 可能會有不同的業務狀态碼,監控時可以依據具體的情況定制。3xx:請求被重定向。如果出現了大量的重定向,一般就表明該網頁存在一定的問題,而且也存在降低使用者使用體驗的風險。4xx:無法通路,比如我們常見的 403 無權限、404 未找到。4xx 說明業務邊界存在問題,可能會導緻身份資訊出現問題或者頁面通路異常。5xx:這個在後端比較常見,如果伺服器内部出現了錯誤,通常也會伴随着通路出現錯誤。
  3. 請求時間:從伺服器發起請求,到伺服器傳回資料内容的總計時間,一般也叫響應耗時。響應耗時可以幫助我們了解具體某個接口或者頁面的執行情況。在“04 課時”中我介紹了直方圖和分位值圖,通過這 2 種或者是其他的形式展示響應耗時,也更能直覺了解耗時的整體分布情況。
  4. SLA:同 QPS 一樣,我也在“04 課時”中介紹過。在這裡我簡單說明一下,在 HTTP 請求層面,SLA 一般可以通過總共的請求數與 5xx 請求數之間的運算獲得。
  5. 獨立使用者數:指的是總共有多少個使用者通路。使用者數越多,說明産品使用的人數越多,使用者基數越大。通過檢視獨立使用者數也可以發現一些問題,比如爬蟲在爬取你的資料,就可能會導緻 QPS 偏高,而使用者數很少的情況。

資料處理

資料處理和一些第三方架構的互動居多,在請求資料處理時,會涉及很多的内容,其中有以下幾個比較關鍵的名額類型:

  1. RPC:你的應用程式一定會有微服務的概念,而且系統之間肯定也會存在 RPC 調用。那麼,在調用時就肯定會涉及消費者和提供者。你就可以分别記錄消費者和提供者的調用次數、成功率、耗時等資訊。 為什麼要分别記錄?以成功率來說,消費者一般會有逾時設定。假設逾時設定是 2 秒,提供者第 3 秒才傳回資料,它認為自己成功了,但消費者可能早将其認定為逾時。是以我們在統計資料時,消費者的成功率是更能提現執行情況的,提供者的資料則更多的是參考。
  2. 熔斷限流降級:熔斷、限流、降級在高流量的時代也是一個必不可少的内容,比如阿裡的 Sentinel,Netflix 的 Hystrix。我們一般都是基于 RPC 或者其他資源的使用情況,來設定相應的門檻值進行限流或者熔斷的。熔斷/限流/降級的次數、門檻值,其實也是一個很好的觀測名額,我們可以通過這些名額,更清楚地了解門檻值是否正确、觸發後的處理是否正确,等等。
  3. 資料源:你的系統肯定會涉及各種各樣的第三方資料源,比如最經常使用的 MySQL、ElasticSearch、MongoDB。在這裡,我們會更加關注與這些系統互動時的執行耗時、調用頻次。如果你在和資料庫操作時,出現耗時較高的情況,就代表業務邏輯也出現了問題。
  4. 自定義業務名額:以上所介紹的這些固有名額早已不能滿足我們對名額的要求,是以我們經常會自定義業務名額,以便能更細化地了解系統。在“07課時”中我會對這部分内容進行講解。

元件協作資源

我們的應用程式會和各種的第三方架構進行資源利用,對于它們的資源利用的效率,很大程度上決定了應用的執行效率。我将資源分為 5 大類,分别是 RPC、資料庫、隊列、緩存和請求,再一一介紹每種資源中常見的名額。

  1. RPC:和資料進行中提到的 RPC 類似,元件協作資源中的 RPC 一樣會涉及資源利用。以國内使用最多的 Dubbo 為例,Dubbo 的每一次發送請求和接收請求,都是利用線程池完成的。在使用 Dubbo 的時候,你可以通過監控線程池的資源資訊掌握系統運作的狀态,這其中的名額有總計的線程數、活躍線程數等。

我在工作中就遇到過這樣的情況:因為一個 Dubbo 接口耗時較長,線程池也沒有做到很好的隔離,導緻目前服務的資源完全處于等待狀态,沒有線程可以去處理其他的業務請求,造成了線上的故障。

  1. 資料庫:業務系統與資料庫之間的互動一般會有專門的 TCP 連結資源保持并處理,每個資料庫都有各自的資料協定。是以,我們通常将連結池化,以提高資源使用效率,不浪費資源。并監控活躍數、閑置數和總共的資源數。當資源缺少時,我們需要注意,是否是配置不足導緻的資源減少。
  2. 隊列:對于異步和大量需要處理的任務,我們通常會使用隊列,以起到削峰的作用。是以我們也會監控任務的發送量、處理量、Lag 值、處理耗時,確定不會出現大面積的延遲進而影響業務處理的情況。
  3. 緩存:緩存架構也經常會在系統中使用,正确使用它可以減少部分資料庫查詢的壓力,進而提升我們接口的響應性能,比如拉勾教育中就會經常用 Redis 作為部分資料的查詢緩存。在緩存中,我們通常會更加關注命中率、記憶體使用率、資料量等名額。尤其是命中率,命中率越高表明接口性能越高,而接口性能可以縮短響應耗時。
  4. 請求:系統經常會依賴于其他需要進行 HTTP 請求等方式的第三方服務,像微信的建立訂單,就需要通過 HTTP 的請求,建立訂單後再傳回資料。在這裡同樣要監控其請求數、耗時情況等名額。雖然這是個常見的現象,但在與第三方服務通信的時候,我們一定要做好熔斷降級政策,最好不要因為第三方服務的不穩定導緻自己業務的主流程受到阻礙。

VM 監控

我們的 Java 程式一般運作在 JVM 上,JVM 我想你一定不陌生。在 JVM 上也有很多的名額,其中有幾個是需要我們關注的:

  1. GC:GC 我想應該是不用特别說明的,我們通常會收集 GC 的次數、每次 GC 時收集了多大的記憶體空間資料。
  2. 記憶體:記憶體可以分為年輕代、老年代、堆外、Meta 區這 4 個部分。如果老年代長期占有率較高,則有可能存在記憶體洩漏的問題。我們可以分别觀測上面 4 個部分的目前值和最大值,來了解記憶體的使用量。
  3. CPU 占用率:這裡指的是程序啟動時 CPU 占用率,通過這個值我們可以看出這個應用是否會頻繁地使用 CPU。出現問題時,如果 CPU 占用率居高不下,可能它并不是問題的根源,而僅僅是任務處理不過來。
  4. 類加載:程式啟動後,一定會進行一定類的加載和解除安裝。監控目前總共的類加載和類解除安裝的數量,也是很好地觀察問題的方式。如果持續出現大量的類被加載的情況,有可能是使用動态代碼生成架構時出現了問題。大量的類被加載會不停地占用 Meta 區,最終導緻堆溢出。
  5. 線程:線程資料也是必不可少的觀察名額之一。程式代碼都是運作線上程上的,如果目前活躍的線程數過多,會使 CPU 資源過高,最終因為資源占用問題,導緻任務執行緩慢。我們一般會監控線程中的活躍線程數、總計線程數、等待線程數等名額。元件

元件在開發中是必不可少的内容,它們既是資料最終存儲的位置,也是資料中轉的地方。元件的好壞,很大程度決定了我們應用程式的好壞。在“05 課時 | 監控名額:如何通過分析資料快速定位系統隐患?(上)”中,我介紹了“元件協作資源”,裡面講到了資料庫、隊列和緩存資源中常見的名額,這裡我再補充一個“網關層”。我們來看看這 4 個資源中的元件在運作之後,又有哪些需要監控的名額。

資料庫

資料庫的種類很多,比如傳統的關系型資料庫,還有現在比較常用的 NoSQL,都有着相當豐富的實作方式。因為它們各自的實作方式不同,是以其需要監控的名額也不同。我會列舉一些它們之間相對通用的一些功能中的名額資訊,一般這些名額出現問題時,會極大地影響到接口的性能。

  1. QPS:每秒查詢次數。可以說每個資料庫都會涉及查詢請求。通過觀測這個名額,我們可以很快了解到系統對資料庫的查詢量,以及是否需要優化查詢語句。
  2. 查詢耗時:查詢耗時可以了解到系統的查詢效率是否處于正常的區間,如果出現了“**慢查詢”**現象,可以及時地處理,比如 MySQL 中可以通過增加索引來解決部分查詢效率的問題,ElasticSearch 則需要篩選出查詢慢的語句再逐個優化。
  3. TPS:每秒事務數。這裡一般指的是對資料的添加/删除/修改操作的處理速度。TPS 不同于 QPS,它涉及修改資料,因為大多數的資料庫在設計時的初衷都是以查詢為主,是以 TPS 在處理時會花費更多的時間。
  4. 主從延遲數:主從的架構可以說是很多資料庫都會有的一種叢集方式,主從架構中有許多實作方式是基于從機器到主機器上同步資料的方式來完成的,比如 MySQL。是以同步時的主從延遲數是一個十分關鍵的名額。延遲數高說明業務系統在讀取資料時,如果恰好讀到了延遲比較高的資料節點,此時系統有可能出現錯誤。
  5. 連接配接數:如果業務系統與資料庫的連接配接達到了一定的數量,則可能造成資料庫處理緩慢。是以,資源的連接配接數也是一個很重要的名額,一般這個名額和這個資料庫的最大連接配接數會有一個的對比,通過這個對比可以展現出這個資料庫的資源配置設定是否均衡。
  6. 資料量:如果資料庫中單個表的資料量大于某個數值,同樣會出現性能問題,比如阿裡巴巴在《Java 開發手冊》中規定,單表超過 500 萬條資料後就要分庫分表處理。一個表的資料量過大會影響查詢、插入的效率,這個規定同樣适用于當下的很多資料庫。
  7. VM 監控:某些元件是基于某些語言開發的,是以它們還會有相對應開發語言的名額監控,比如 ElasticSearch 基于 Java 開發,是以還要監控 JVM 的資訊。

除了以上這些,肯定還有很多我沒有提到的名額。每個資料庫不同的實作方式會細化出更多有獨特性的統計名額。我所講到的這 7 個,在各個資料庫中擁有共通性,并且它們可以幫助我們初步認定一些問題的原因。

隊列

在“05 課時”中我對隊列有過介紹了,它通常用來處理異步和大量的任務,隊列中需要監控的通用名額一般有以下 4 個:

  1. Lag:目前待消費的資料量的大小。如果這個值持續增長并且過大,則說明消費者的能力已經不能夠滿足生産者的生産速度了。這時候一般會考慮減少生産者生産的内容,或者加快消費者速度,如果可以的話加機器來運作也不失是一個好的選擇。
  2. 發送數量:生産者生産資料的内容大小。如果這個值增長的速度越快則代表生成内容的數量越多。如果值突然飙升得比較高,也應該注意,是否存在無用内容的發送。
  3. 消費數量:消費端消費生産者内容的數量。一般的隊列中間件中都會有分區的概念,通過消費數量可以清楚看到每個分區的消費情況,如果出現了某個分區消費數量明顯不足的情況,則需要針對某個分區的消費執行個體做特殊觀察。
  4. 分區數:一般在 1 個 topic 中,我們會将資料分區來提高并行消費的速度,這個分區的數量就是分區數。分區數同樣是一個很關鍵的概念,如果一個 topic 的分區數相對較少,說明可以交給消費者消費的線程數也不多。

緩存

緩存如我之前所講的,也是一個十分重要的部分,如果正确使用它則可以減少部分資料庫查詢的壓力,進而提升我們接口的響應性能,緩存中也有十分多的關鍵名額:

  1. 響應時間:說到緩存中的關鍵名額,首先就要說到響應時間。一般這個名額的值都很低,因為緩存大多數時候是存儲在記憶體中的。如果這個值偏高,說明使用方或者緩存出現了問題,這時就需要從更細的次元跟蹤問題的原因了。
  2. 緩存命中率:命中率其實就是請求中查詢到資料的請求除請求總數,最終獲得的百分比。百分比越高說明命中率越高,程式也會有更好的性能;如果命中率相對較低,則要考慮是否是寫法出現了問題,或者是這個内容适不适合使用緩存。如果不适合的話可以考慮不用緩存,因為引入了一個新的元件,會增加運維和開發的成本。
  3. 網絡延遲時間:對緩存來說,如果互動中出現了較高的延遲會影響到業務系統,因為緩存一般的調用頻率都不低,如果延遲較高的話,會影響接口的性能,是以保證網絡延遲低也是一個很關鍵因素。
  4. 已使用記憶體:緩存一般是存儲在記憶體中的,是以對于記憶體的使用量有嚴格的要求,如果沒有滿足要求,緩存系統會執行淘汰政策,比如 LRU。執行淘汰政策之後可能會導緻緩存命中率下降,而如果記憶體使用過高,緩存系統則被系統 kill。
  5. 資源連結:除了與資料庫,業務系統還會與緩存系統有連結的情況,是以我們也需要監控它們的連結情況。我們常被用作緩存的 Redis,它其實也是一種 KV 類型的 NoSQL 資料庫。
  6. 緩存數量:資料庫中已有的緩存數量也是一個很好的名額。如果出現了使用記憶體達到配置門檻值,導緻緩存使用了一定的算法來淘汰緩存。通過緩存數量也可以清楚地看到我們系統中新增的緩存或是被移除緩存的數量對比,了解我們的系統是否是一直在有效地利用緩存提高性能。

網關層

我在“02 | 系統日志:何以成為保障穩定性的關鍵?”這一課時中介紹過網關層。請求從用戶端過來,一般會先經過網關層,由網關層統一接收管理所有的請求。是以,在網關層也有一些名額是可以監控的:

  1. 請求相關:同我在“05 課時”中講應用程式中的名額時一樣,在網關層你也需要關注 QPS、狀态碼、請求耗時等資訊。網關層裡往往會記錄請求整體的執行情況。這裡的資料肯定是最全、最準的。
  2. 錯誤數:如果網關層出現了錯誤請求資訊,由于網關層是高于應用層的,是以應用層中的請求一般是由網關層轉發,資訊根本不會進入應用層。是以當在網關層出現錯誤數飙升的問題時,在應用層可能根本無法定位問題的原因。
  3. 請求處理:網關層有相關的請求處理機制,是以監控請求處理相關的資料也十分關鍵,比如總請求數、正處于“讀”狀态的請求數、正處于“寫”狀态的請求數、正在排隊的請求數。如果出現大量的排隊現象,則說明網關層已經處理不過來了,這時候一般可以通過增加網關機器來解決。

機器資訊

最後我們來說說機器的統計資訊。機器的處理性能如果不夠好,會直接影響服務的運作情況,畢竟服務是依托機器運作。機器資訊的名額可以按照組成部分,分為以下幾個:

  1. CPU:CPU 的運作情況肯定是應用程式中最重要的。我們一般會比較關注 CPU 的整體使用率,然後再細分為系統側、使用者側的使用率。同樣,我們也會關注系統的 Load 情況,如果 Load 值越高說明系統承受的處理任務越多,系統執行也會更緩慢。
  2. 記憶體:記憶體的大小會影響程式的可使用記憶體空間,除了重記憶體使用程式。記憶體中我們也會關注記憶體的整體使用率,以及 swap 區的使用率。一般我不太建議使用 swap 區,因為它會利用磁盤的空間來代替記憶體,而這可能會影響到程式的使用性能。如果 swap 區的使用率較高,可以考慮将其關閉,通過更新記憶體來提高程式性能。
  3. 磁盤:在一般的應用程式中,磁盤更多的是用于日志記錄和臨時緩存檔案記錄。同 CPU 和記憶體一樣,關注磁盤的使用率即可。
  4. 網絡:網絡情況可以說是現在應用中的重中之重,無論是連結元件還是微服務中的 RPC,到處都有伺服器之間的通信。一般我們會更關注出/入流量,如果當到達網卡限制的大小後,則一般隻能考慮擴容服務來解決,因為網卡的提升是有限的。在此之外,我們還會監控網絡丢包率、連接配接錯誤數等資訊,這些資訊可以幫助我們的程式在網絡出現問題時,判斷是否是網卡的原因。
  5. I/O:在 Linux 平台中,任何的網絡請求、消息或是其他内容都是基于檔案來構成的,是以 I/O 在 Linux 中無處不在。我們會更關注 I/O 的檔案讀取/寫入中的速度、耗時、次數等資訊,這些都是最能直覺展現出寫入和讀取速度的内容。同時我們還會關注使用率(util),如果磁盤的使用率過高,則說明應用對磁盤的使用量很大,很有可能會因為磁盤的問題而導緻應用程式上的問題。
  6. 句柄:随着 I/O 的使用,我們也需要關注句柄的使用量。如果程式中出現了資源流未關閉的情況,則有可能會導緻句柄數激增,最終導緻句柄耗盡,影響程式執行。在“04 | 統計名額:"五個九"對系統穩定的意義?”這一課時中,我就說到了之前我們就曾出現過因 HTTP 中流未關閉,使句柄耗盡,導緻程式無法再次發起 HTTP 請求。

結語

至此,對監控名額的介紹就告一段落了,從使用者側到伺服器,我向你介紹端上通路、應用程式、元件、機器資訊中需要監控的名額以及常見的問題狀況及解決辦法,希望能對你的工作有一定的幫助。那麼,你認為在元件和機器中還有哪些你經常關注的名額?

名額是保證系統穩定不可或缺的一環,它同日志一樣,在每個端都有很多的名額資料。

繼續閱讀