使用Metrics監控應用程式的效能
在編寫應用程式的時候,通常會記錄日誌以便事後分析,在很多情況下是產生了問題之後,再去檢視日誌,是一種事後的靜態分析。在很多時候,我們可能需要了解整個系統在當前,或者某一時刻執行的情況,比如當前系統中對外提供了多少次服務,這些服務的響應時間是多少,隨時間變化的情況是什麼樣的,系統出錯的頻率是多少。這些動態的準實時資訊對於監控整個系統的執行健康狀況來說很重要。
一些應用程式,比如對外提供介面或者服務的WebService,對整個系統的實時執行情況進行監控顯得尤為重要,著就像我們作業系統裡面的資源管理器一樣,如果能夠實時或者準實時的看到整個系統耗費的CPU,記憶體等資源,對我們快速對系統做出響應,以及優化很重要。並且,這些實時的效能引數資訊,對於一些高階應用場景,比如
前幾天在InfoQ的一篇採訪文章中看到一句話 “Profiling特別重要。如果能有一個特別強大的Profiling系統,就知道整個系統在哪個地方,哪臺機器上,花了多少CPU、記憶體、磁碟IO或者網路頻寬等資源,才能知道優化什麼地方效益最大。”
同樣,對於WebService的監控,比如在那個地方,那臺機器上,花了多少CPU,多少記憶體,每一個服務的響應時間,出錯的次數頻率等,這些資訊記錄下來之後,我們就可以看到服務在執行時的動態的表現,更加容易找出錯誤或者定位問題點來進行優化。
最簡單的做法是,在應用系統的關鍵地方,或者所有程式的入口,出口進行埋點,然後將這些取樣資訊不斷的傳送到某一個訊息佇列或者記憶體DB中,然後其他系統進行讀取分析和展示。
在Java中有一個開源的名為Metrics的專案,它能夠捕獲JVM以及應用層面的效能引數,他的作者Coda Hale介紹了什麼是Mertics並且為什麼Metrics在應用程式系統中很有必要,視訊和演講可以分別到YouTube和SlideShare上可以下載。在.NET中有對其進行移植的專案叫 Metrics.NET。
在開始介紹Metric之前,需要先看看一些基本的度量器型別,以及常見的使用場景,才能知道如何使用。
一 度量型別
Metrics提供5種基本的度量型別:Gauges, Counters, Histograms, Meters和 Timers
Gauge
Gauge是最簡單的度量型別,只有一個簡單的返回值,他用來記錄一些物件或者事物的瞬時值。
比如,我們型別為Gauge的計數器來記錄某個服務目前開通的城市個數
Metric.Gauge("Service Cities Count", () => Cities.Count, new Unit("個"));
Counters
Counter是一個簡單64位的計數器,他可以增加和減少。
比如我們可以定義兩個Counter型別的計數器,用來統計所有服務請求數目,和目前正在處理的請求總數。
/// <summary> /// keep the total count of the requests /// </summary> private readonly Counter totalRequestsCounter = Metric.Counter("Requests", Unit.Requests); /// <summary> /// count the current concurrent requests /// </summary> private readonly Counter concurrentRequestsCounter = Metric.Counter("SampleMetrics.ConcurrentRequests", Unit.Requests);
這樣,在我們請求處理開始的時候,同時將這兩個計數器自增。
this.concurrentRequestsCounter.Increment(); // increment concurrent requests counter this.totalRequestsCounter.Increment(); // increment total requests counter
當某一個請求處理完成之後,將目前正在處理的請求減一
this.concurrentRequestsCounter.Decrement(); // decrement number of concurrent requests
這種計數器也可以用來統計諸如當前有多少人線上,或者伺服器中有多少處於有效期內的session
Meters
Meter是一種只能自增的計數器,通常用來度量一系列事件發生的比率。他提供了平均速率,以及指數平滑平均速率,以及取樣後的1分鐘,5分鐘,15分鐘速率。
比如需要統計請求的速率,比如統計平均每分鐘內有多少次請求進來。只需要定義一個metric
/// <summary> /// measure the rate at which requests come in /// </summary> private readonly Meter meter = Metric.Meter("Requests", Unit.Requests,TimeUnit.Seconds);
在處理請求的地方,呼叫Mark方法即可。
this.meter.Mark(); // signal a new request to the meter
再比如,要測量服務出錯的概率,比如每小時出錯多少次。可以定義一個metric。
/// <summary> /// measure the rate of service exception /// </summary> private readonly Meter errorMeter = Metric.Meter("Error", Unit.Errors, TimeUnit.Hours);
這樣,在處理請求的時候,如果出現異常了,呼叫一下errorMeter的Mark方法即可。
this.errorMeter.Mark();// signal a new error to the meter
Histograms
Histrogram是用來度量流資料中Value的分佈情況,Histrogram可以計算最大/小值、平均值,方差,分位數(如中位數,或者95th分位數),如75%,90%,98%,99%的資料在哪個範圍內。
比如,我們想度量,所有傳進來服務的請求引數的長度分佈。那麼,可以定義一個histogram。
/// <summary> /// keep a histogram of the input data of our request method /// </summary> private readonly Histogram histogramOfData = Metric.Histogram("ResultsExample", Unit.Items);
然後在請求的地方,呼叫其Update方法來更新值。
this.histogramOfData.Update(request.length, methodName); // update the histogram with the input data
Timer
Timer是Histogram跟Meter的一個組合,比如要統計當前請求的速率和處理時間。
就可以定義一個Timer:
/// <summary> /// measure the time rate and duration of requests /// </summary> private readonly Timer timer = Metric.Timer("Requests", Unit.Requests);
在使用的時候,呼叫timer的NewContext即可。
using (this.timer.NewContext(i.ToString())) // measure until disposed { ... }
二 度量資料的輸出
收集了這麼多資料之後,我們需要把資料時實的動態展示或者儲存起來。Metric提供了多種的資料報告介面。包括自帶的Metrics.NET.FlotVisualization, 以及輸出到專業的系統監控Graphite,輸出到開源,分散式,時間序列的中InfluxDB,或者輸出到ElasticSearch中。配置起來也非常簡單。比如如果要直接在http頁面上展現,只需要在初始化的時候,設定合適的EndPoint即可:
Metric.Config .WithHttpEndpoint("http://localhost:1234/metrics/") .WithAllCounters() .WithInternalMetrics() .WithReporting(config => config .WithConsoleReport(TimeSpan.FromSeconds(30))
上面自帶的效能DashBoard略顯簡陋。 通常,我們一般會將這些實時採集的資料儲存到分散式時序資料庫InfluxDB中,然後利用開源的圖表控制元件Grafana來實時展現這些資料,比如,可以製作想下面這樣的,動態的效能準實時監控系統:
三 總結
本文介紹瞭如何使用埋點和各種度量工具來實時監測應用程式的效能,介紹了.NET中Metrics度量工具的使用。與傳統的記錄日誌的方式不同,這種實時或者準實時的對當前系統各種關鍵指標的取樣和監控,對於應用程式的運維,效能優化,提供了一種動態的視角,能幫助我們更好的瞭解當前應用程式或者服務在線上的各種效能引數和表現狀態。Metrics的取樣應該儘量減少對原有系統的侵入性,所以一般的最好是將取樣的結果儲存到訊息佇列或者記憶體DB中,然後進行動態展示,另外取樣頻率也是需要考慮的一個重要因素。因為對於一個較大的系統來說,實時取樣產生的資料量會比較大。InfluxDB 似乎只能在非Windows平臺使用,所以本文沒有完整演示整個Metrics+InfluxDB+Grafana 構建應用程式實時監控系統的搭建。不過相信大家對照著相關文件,應該不難實現。
希望本文對您瞭解如何實時監控應用程式效能,以及如何構建應用程式效能引數dashboard有所幫助。