分佈式系統之全棧監控

首先,我們需要全棧系統監控,它就像是我們的眼睛,沒有它,我們就不知道系統到底發生了什麼,我們將無法管理或是運維整個分佈式系統。所以,這個系統是非常非常關鍵的。

而在分佈式或 Cloud Native 的情況下,系統分成多層,服務各種關聯,需要監控的東西特別多。沒有一個好的監控系統,我們將無法進行自動化運維和資源調度。

這個監控系統需要完成的功能爲:

全棧監控;
關聯分析;
跨系統調用的串聯;
實時報警和自動處置;
系統性能分析。

多層體系的監控

所謂全棧監控,其實就是三層監控。

基礎層:監控主機和底層資源。比如:CPU、內存、網絡吞吐、硬盤 I/O、硬盤使用等。
中間層:就是中間件層的監控。比如:Nginx、Redis、ActiveMQ、Kafka、MySQL、Tomcat 等。
應用層:監控應用層的使用。比如:HTTP 訪問的吞吐量、響應時間、返回碼、調用鏈路分析、性能瓶頸,還包括用戶端的監控。

這還需要一些監控的標準化。

日誌數據結構化;
監控數據格式標準化;
統一的監控平臺;
統一的日誌分析。

什麼纔是好的監控系統

這裏還要多說一句,現在很多的監控系統都做得很不好,它們主要有兩個很大的問題。

1、監控數據是隔離開來的。因爲公司分工的問題,開發、應用運維、系統運維,各管各的,所以很多公司的監控系統之間都有一道牆,完全串不起來。
2、監控的數據項太多。有些公司的運維團隊把監控的數據項多做爲一個亮點到處講,比如監控指標達到 5 萬多個。老實說,這太丟人了。因爲信息太多等於沒有信息,抓不住重點的監控纔會做成這個樣子,完全就是使蠻力的做法。

一個好的監控系統應該有以下幾個特徵。

關注於整體應用的 SLA。主要從爲用戶服務的 API 來監控整個系統。
關聯指標聚合。 把有關聯的系統及其指標聚合展示。主要是三層系統數據:基礎層、平臺中間件層和應用層。其中,最重要的是把服務和相關的中間件以及主機關聯在一起,服務有可能運行在 Docker 中,也有可能運行在微服務平臺上的多個 JVM 中,也有可能運行在 Tomcat 中。總之,無論運行在哪裏,我們都需要把服務的具體實例和主機關聯在一起,否則,對於一個分佈式系統來說,定位問題猶如大海撈針。
快速故障定位。 對於現有的系統來說,故障總是會發生的,而且還會頻繁發生。故障發生不可怕,可怕的是故障的恢復時間過長。所以,快速地定位故障就相當關鍵。快速定位問題需要對整個分佈式系統做一個用戶請求跟蹤的 trace 監控,我們需要監控到所有的請求在分佈式系統中的調用鏈,這個事最好是做成沒有侵入性的。

如何做出一個好的監控系統

服務調用鏈跟蹤。這個監控系統應該從對外的 API 開始,然後將後臺的實際服務給關聯起來,然後再進一步將這個服務的依賴服務關聯起來,直到最後一個服務(如 MySQL 或 Redis),這樣就可以把整個系統的服務全部都串連起來了。這個事情的最佳實踐是 Google Dapper 系統,其對應於開源的實現是 Zipkin。對於 Java 類的服務,我們可以使用字節碼技術進行字節碼注入,做到代碼無侵入式。

服務調用時長分佈。使用 Zipkin,可以看到一個服務調用鏈上的時間分佈,這樣有助於我們知道最耗時的服務是什麼。

服務的 TOP N 視圖。所謂 TOP N 視圖就是一個系統請求的排名情況。一般來說,這個排名會有三種排名的方法:a)按調用量排名,b) 按請求最耗時排名,c)按熱點排名(一個時間段內的請求次數的響應時間和)。

數據庫操作關聯。對於 Java 應用,我們可以很方便地通過 JavaAgent 字節碼注入技術拿到 JDBC 執行數據庫操作的執行時間。對此,我們可以和相關的請求對應起來。

服務資源跟蹤。我們的服務可能運行在物理機上,也可能運行在虛擬機裏,還可能運行在一個 Docker 的容器裏,Docker 容器又運行在物理機或是虛擬機上。我們需要把服務運行的機器節點上的數據(如 CPU、MEM、I/O、DISK、NETWORK)關聯起來。

這樣一來,我們就可以知道服務和基礎層資源的關係。如果是 Java 應用,我們還要和 JVM 裏的東西進行關聯,這樣我們才能知道服務所運行的 JVM 中的情況(比如 GC 的情況)。

有了這些數據上的關聯,我們就可以達到如下的目標。

1、當一臺機器掛掉是因爲 CPU 或 I/O 過高的時候,我們馬上可以知道其會影響到哪些對外服務的 API。
2、當一個服務響應過慢的時候,我們馬上能關聯出來是否在做 Java GC,或是其所在的計算結點上是否有資源不足的情況,或是依賴的服務是否出現了問題。
3、當發現一個 SQL 操作過慢的時候,我們能馬上知道其會影響哪個對外服務的 API。
4、當發現一個消息隊列擁塞的時候,我們能馬上知道其會影響哪些對外服務的 API。

總之,我們就是想知道用戶訪問哪些請求會出現問題,這對於我們瞭解故障的影響面非常有幫助。

一旦瞭解了這些信息,我們就可以做出調度。比如:

一旦發現某個服務過慢是因爲 CPU 使用過多,我們就可以做彈性伸縮。
一旦發現某個服務過慢是因爲 MySQL 出現了一個慢查詢,我們就無法在應用層上做彈性伸縮,只能做流量限制,或是降級操作了。

所以,一個分佈式系統,或是一個自動化運維繫統,或是一個 Cloud Native 的雲化系統,最重要的事就是把監控系統做好。在把數據收集好的同時,更重要的是把數據關聯好。這樣,我們纔可能很快地定位故障,進而才能進行自動化調度。



上圖只是簡單地展示了一個分佈式系統的服務調用鏈接上都在報錯,其根本原因是數據庫鏈接過多,服務不過來。另外一個原因是,Java 在做 Full GC 導致處理過慢。於是,消息隊列出現消息堆積堵塞。這個圖只是一個示例,其形象地體現了在分佈式系統中監控數據關聯的重要性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章