我們一起聊聊分布式架構(gòu)中的可觀測性,看你了解幾分?
架構(gòu)
隨著分布式架構(gòu)逐漸成為主流,“可觀測性”一詞也日益頻繁地被人提起,它涉及的范圍比較廣泛,主要概括為如下三類:
- 聚合度量(metrics)
 - 事件日志(logging)
 - 鏈路追蹤(tracing)
 
這三個方向雖然各有千秋,各有側(cè)重,但是又不完全獨立。在Peter Bourgon 的文章《Metrics, Tracing, and Logging》系統(tǒng)地闡述了這三者的定義、特征,以及它們之間的關(guān)系與差異,受到了業(yè)界的廣泛認可。

在實際的工作中,大家或多或少對上面三種都有一定的了解,只是沒有機會或者沒有需求去深入研究。
聚合度量(Metrics)
度量是一種計量單位,它是指對系統(tǒng)中某一指標(biāo)的統(tǒng)計聚合,然后通過聚合信息來揭示系統(tǒng)整體的運行狀況。
度量總體上可分為客戶端的指標(biāo)收集、服務(wù)端的存儲查詢以及終端的監(jiān)控預(yù)警三個相對獨立的過程,每個過程一般都是不同的組件來完成,以Prometheus為例:

指標(biāo)可以通過直接抓取各種exporters,也可以從pushgateway抓取,然后存儲在TSDB(時序數(shù)據(jù)庫)中,查詢指標(biāo)可以通過grafana,也可以通過prometheus web,報警則是通過altermanager實現(xiàn)。
可以看到,一個度量工具的內(nèi)部實現(xiàn)是很復(fù)雜的,在使用的時候也會損耗一定的資源。
目前來說,在云原生領(lǐng)域中,Prometheus占據(jù)了很大的主導(dǎo)地位,嚴格來說,它已經(jīng)成云原生監(jiān)控的標(biāo)配,下面我主要以Prometheus為例進行介紹。
指標(biāo)收集
指標(biāo)收集主要包括兩部分:
- 指標(biāo)定義
 - 指標(biāo)收集
 
相比于收集,指標(biāo)定義尤為重要,良好的指標(biāo)定義可以更直觀的反應(yīng)系統(tǒng)狀態(tài)。
最常用的黃金指標(biāo)有:
- 延遲:延遲是信息的發(fā)送方和接收方之間的時間延遲,以毫秒(ms)為單位。其原因通常是由于數(shù)據(jù)包丟失、網(wǎng)絡(luò)擁塞和稱為 “數(shù)據(jù)包延遲差異” 的網(wǎng)絡(luò)抖動。延遲直接影響客戶體驗,轉(zhuǎn)化為成功請求的延遲和失敗請求的延遲。
 - 流量:流量是系統(tǒng)上完成的工作量所帶來的壓力。它通過每秒查詢數(shù) (QPS) 或每秒事務(wù)數(shù) (TPS) 來衡量。企業(yè)通過數(shù)量來衡量這一點:關(guān)鍵績效指標(biāo) (KPI) 是在給定時間訪問網(wǎng)站的人數(shù)。這是與商業(yè)價值的直接關(guān)系。
 - 錯誤:錯誤是根據(jù)整個系統(tǒng)中發(fā)生的錯誤來衡量的。什么被視為服務(wù)錯誤率的重要指標(biāo)!有兩類錯誤,顯式錯誤,例如失敗的 HTTP 請求(例如,500 個錯誤代碼)。而一個隱含的錯誤將是一個成功的響應(yīng),但與錯誤的內(nèi)容或響應(yīng)時間長。
 - 飽和度:飽和度定義了服務(wù)的過載程度。它衡量系統(tǒng)利用率,強調(diào)資源和服務(wù)的整體能力。這通常適用于 CPU 使用率、內(nèi)存使用率、磁盤容量和每秒操作數(shù)等資源。儀表板和監(jiān)控告警是幫助您密切關(guān)注這些資源并幫助您在容量變得飽和之前主動調(diào)整容量的理想工具。
 - 利用率:雖然不是 “四大金信號” 的一部分,但值得一提;利用率告訴資源或系統(tǒng)有多忙。它以 %(百分比)表示,范圍為 0–100%。
 
所以在做指標(biāo)定義的時候,可以結(jié)合以上的黃金指標(biāo)進行分類,但是并不代表每一種類型的應(yīng)用都需要滿足以上所有指標(biāo)。以系統(tǒng)監(jiān)控為例,如下表示是否需要監(jiān)控該類指標(biāo):

定義好資源指標(biāo)后,再來定義指標(biāo)具體的獲取方法。
目前,基于Prometheus監(jiān)控所實現(xiàn)的Exporter非常多,這些Exporter基本能夠拿到我們想要的指標(biāo),比如:

指標(biāo)查詢
指標(biāo)收集到Prometheus之后,會存儲到它的TSDB(時序數(shù)據(jù)庫)中,我們可以在Prometheus Web中查詢需要的指標(biāo),如下獲取不同時間節(jié)點kubelet的HTTP請求總數(shù):

監(jiān)控預(yù)警
指標(biāo)度量是手段,最終目的是做分析和預(yù)警。
我們可以通過這些指標(biāo)制作監(jiān)控大屏,隨時觀察系統(tǒng)的狀態(tài),如下可以實時監(jiān)控Kubernetes中容器以及節(jié)點的狀態(tài):

良好的可視化能力對于提升度量系統(tǒng)的產(chǎn)品力十分重要,長期趨勢分析(譬如根據(jù)對磁盤增長趨勢的觀察判斷什么時候需要擴容)、對照分析(譬如版本升級后對比新舊版本的性能、資源消耗等方面的差異)、故障分析(不僅從日志、追蹤自底向上可以分析故障,高維度的度量指標(biāo)也可能自頂向下尋找到問題的端倪)等分析工作,既需要度量指標(biāo)的持續(xù)收集、統(tǒng)計,往往還需要對數(shù)據(jù)進行可視化,才能讓人更容易地從數(shù)據(jù)中挖掘規(guī)律。
還可以對重要的指標(biāo)進行告警,以便維護人員能夠及時地介入排查問題,如下是一個應(yīng)用JVM使用過載的告警。

但是,在做告警的時候需要綜合考慮指標(biāo)的重要程度,不是所有指標(biāo)都需要告警,不然就容易造成告警風(fēng)暴,最后就會真實演繹《狼來了》的故事。
事件日志(Logging)
日志用來記錄系統(tǒng)運行期間所發(fā)生的事件,每個系統(tǒng)都應(yīng)該有日志。
日志是排查問題的重要手段,大部分系統(tǒng)問題最終都會追溯到日志上,所以良好的日志記錄有助于快速定位系統(tǒng)問題。
但是,目前基本都是微服務(wù)多節(jié)點的形式存在,沒辦法像單機時代那樣簡單使用命令就能獲取到日志內(nèi)容。而是需要把日志收集到專門的日志系統(tǒng),然后再進行查詢、分析等。
目前比較受歡迎的開源日志系統(tǒng)是ELK或者EFK,它在日志領(lǐng)域有著不可撼動的地位。

事件日志也涉及以下幾個方面:
- 日志輸出
 - 日志收集
 - 日志查詢
 - 日志告警
 
日志輸出
一千個開發(fā)可能有一千個日志輸出方式,而且輸出的內(nèi)容千奇百怪,不管重要的或者不重要的都輸出到日志里,這將會導(dǎo)致日志查看困難,干擾大。
所以,良好的日志記錄習(xí)慣是非常重要的,在企業(yè)中應(yīng)該有專門的日志規(guī)范,這樣可以統(tǒng)一格式、統(tǒng)一標(biāo)準,不僅有助于收集,也有助于查看。
打印日志應(yīng)該盡量做到以下幾點:
- 記錄請求的TraceID
 - 記錄關(guān)鍵事件,包括上下文
 - 不要打印敏感信息
 - 合理規(guī)劃日志級別
 
日志收集
對于分布式服務(wù),為了能同時看到跨節(jié)點的全部日志,就需要把各種日志統(tǒng)一收集,比如使用Logstash或者Filebeat來收集日志,在日志收集的同時還可以對日志進行處理,比如同一個應(yīng)用的日志可以建一條索引,同一個應(yīng)用的索引可以按天進行創(chuàng)建等,這樣避免索引過大導(dǎo)致查詢困難等問題。
如果在日志收集的過程中發(fā)現(xiàn)日志比較大,可以在收集處理的過程中先把日志寫入緩存或者消息隊列,避免直接寫入Elasticsearch導(dǎo)致其壓力過載。
日志查詢
收集到的日志最終是存儲在Elasticsearch中,它通常搭配Kibana一起使用,方便用戶操作。
Kibana 盡管只負責(zé)圖形界面和展示,但它提供的能力遠不止讓你能在界面上執(zhí)行 Elasticsearch 的查詢那么簡單。Kibana 宣傳的核心能力是“探索數(shù)據(jù)并可視化”,即把存儲在 Elasticsearch 中的數(shù)據(jù)被檢索、聚合、統(tǒng)計后,定制形成各種圖形、表格、指標(biāo)、統(tǒng)計,以此觀察系統(tǒng)的運行狀態(tài),找出日志事件中潛藏的規(guī)律和隱患。按 Kibana 官方的宣傳語來說就是“一張圖片勝過千萬行日志”。

日志告警
在做日志輸出的時候,對于一些有破壞性的日志需要特別標(biāo)記,當(dāng)遇到這類日志就需要及時的通知維護人員。我們可以使用ElastAlert來進行告警處理。
ElastAlert是三方插件,通過查詢 ElasticSearch 中的記錄進行比對,通過配置報警規(guī)則對匹配規(guī)則的日志進行警報。 ElastAlert 將Elasticsearch與兩種類型的組件(規(guī)則類型和警報)結(jié)合使用,定期查詢Elasticsearch,并將數(shù)據(jù)傳遞到規(guī)則類型,該規(guī)則類型確定何時找到匹配項。發(fā)生匹配時,將為該警報提供一個或多個警報,這些警報將根據(jù)匹配采取行動。
鏈路追蹤(Tracing)
有了度量和日志,在多數(shù)情況下已經(jīng)能滿足日常使用,但是它們有一個弊端,就是沒辦法很直觀的查看上下文,也無法有效的追蹤某個請求。
所以,就引入了鏈路追蹤。
從目標(biāo)來看,鏈路追蹤的目的是為排查故障和分析性能提供數(shù)據(jù)支持,系統(tǒng)對外提供服務(wù)的過程中,持續(xù)地接受請求并處理響應(yīng),同時持續(xù)地生成 Trace,按次序整理好 Trace 中每一個 Span 所記錄的調(diào)用關(guān)系,便能繪制出一幅系統(tǒng)的服務(wù)調(diào)用拓撲圖。根據(jù)拓撲圖中 Span 記錄的時間信息和響應(yīng)結(jié)果(正?;虍惓7祷兀┚涂梢远ㄎ坏骄徛蛘叱鲥e的服務(wù);將 Trace 與歷史記錄進行對比統(tǒng)計,就可以從系統(tǒng)整體層面分析服務(wù)性能,定位性能優(yōu)化的目標(biāo)。
從字面上看鏈路監(jiān)控的實現(xiàn)方式比較簡單,然而在實際工作中卻比較復(fù)雜。主要在于企業(yè)業(yè)務(wù)系統(tǒng)可能采用不同的程序語言 ,每一種程序語言實現(xiàn)的方式都不一樣,這就導(dǎo)致工作量非常巨大,而且還要考慮以下幾點:
- 低損耗:如果接入鏈路監(jiān)控不僅沒有解決問題,反而加大了性能開銷,這就得不償失。
 - 透明:盡量在不加大開發(fā)工作量,最好能做到無侵入接入。
 - 易用:傻瓜式的使用方式比較受歡迎。
 
目前最常用的是Zipkin、Skywalking、Pinpoint等,它們都是基于服務(wù)追蹤實現(xiàn)的。
服務(wù)追蹤的實現(xiàn)思路是通過某些手段給目標(biāo)應(yīng)用注入追蹤探針(Probe),針對 Java 應(yīng)用一般就是通過 Java Agent 注入的。探針在結(jié)構(gòu)上可視為一個寄生在目標(biāo)服務(wù)身上的小型微服務(wù)系統(tǒng),它一般會有自己專用的服務(wù)注冊、心跳檢測等功能,有專門的數(shù)據(jù)收集協(xié)議,把從目標(biāo)系統(tǒng)中監(jiān)控得到的服務(wù)調(diào)用信息,通過另一次獨立的 HTTP 或者 RPC 請求發(fā)送給追蹤系統(tǒng)。
下面是使用Skywalking收集之后的查詢頁面。

最后
可觀測性平臺是一個很大很復(fù)雜的平臺,大部門公司都是用一些開源手段來堆疊,雖然能解決一些問題,但是它們各自是相互獨立的,沒辦法很友好的進行關(guān)聯(lián)。這也導(dǎo)致在排查問題的時候需要各個平臺來回切換,而且每個平臺都需要一定的學(xué)習(xí)成本,這也導(dǎo)致許多公司安裝部署了,但是實際很少去用,沒有發(fā)揮其要實現(xiàn)的效果。
鏈接
【1】https://peter.bourgon.org/blog/2017/02/21/metrics-tracing-and-logging.html
【2】https://skywalking.apache.org/
【3】https://www.elastic.co/cn/















 
 
 


















 
 
 
 