指標采集方法
當前,Prometheus已經成為監控的事實標準,本文也是基于Prometheus來討論監控指標的采集方法。通常來說,指標采集可分為指標生成和指標上報兩個步驟。指標生成是把業務的狀態、性能等數據轉換成符合監控組件格式要求的監控指標;指標上報是把生成后的指標定期的存儲到時序數據庫中,可以通過主動推送或被動拉取的方式上報。
具體到GRPC接口的指標生成來說,可以自定義的方式生成并上報,比如有些系統會在網關中通過中間件統計接口調用數、時延等數據指標,并定期調用時序數據庫的接口將指標推送到服務端,這種方式適合有特殊指標要求的系統。
對于通用的基礎指標,我們可以采用go-grpc-prometheus組件來自動生成常用指標,非常簡單、方便。以golang為例,具體分為以下三個步驟:
1.go mod引入go-grpc-prometheus
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
2.服務注冊
// 注冊GRPC服務
server := grpc.NewServer(opts...)
// 注冊指標采集服務
grpc_prometheus.Register(server)
http.Handle("/metrics", promhttp.Handler())
3.指標拉取
在Prometheus配置target,地址為對應服務的/metrics接口
通過go-grpc-prometheus生成的指標有幾個通用的標簽,大家使用的時候需要關注。
grpc_service
grpc的名稱,由proto包名和服務名組合在一起表示,比如package=common.testproto,服務名為service user,那么標簽該標簽就是 grpc_service=common.testproto.user
grpc_method
grpc的方法名,比如grpc_method="getUser"
grpc_type
grpc請求的類型,分為unary(一個請求,一個回復),client_stream(多個請求,一個回復),server_stream(單個請求,多個回復),bidi_stream(多個請求,多個回復)
grpc_code
接口處理結果的狀態碼,如:OK(正常),IllegalArgument(參數錯誤),DeadlineExceeded(超時),NotFound(不存在)等
重點指標分析
對于服務類的監控,通常關注的是RED三個黃金指標,即請求數量(Request),錯誤率(Error),時延(Duration),在我們采集的指標里面,都有相應的指標可以體現。假設我們現在請求common-srv.testproto.user服務的getUser方法,整個過程會生成以下指標:
一但服務端接收到請求,grpc_server_started_total指標累加1,生成指標:
grpc_server_started_total{grpc_method="getUser",grpc_service="common-srv.testproto.user",grpc_type="getUser"} 1
當服務端邏輯處理結束,帶有狀態碼的grpc_server_handled_total指標累加1,生成指標:
grpc_server_handled_total{grpc_code="OK",grpc_method="getUser",grpc_service="common-srv.testproto.user",grpc_type="getUser"} 1
此外,在請求結束后,會生成三個處理時間相關的指標:
grpc_server_handling_seconds_count:根據狀態碼和方法名分別統計RPC請求數
grpc_server_handling_seconds_sum:根據狀態碼和方法名分別統計RPC請求的總耗時,可以用來計算接口平均時延
grpc_server_handling_seconds_bucket:拆分時間桶計算每個時延區間包含的請求數
告警規則參考
接口總請求數過多
sum(rate(grpc_server_started_total{job="ecx-cloud-common-srv"}[1m])) by (grpc_service) > 10000
錯誤請求過多
sum(rate(grpc_server_handled_total{job="ecx-cloud-common-srv",grpc_type="unary",grpc_code!="OK"}[1m])) by (grpc_service) > 10
錯誤率過高
sum(rate(grpc_server_handled_total{job="ecx-cloud-common-srv",grpc_type="unary",grpc_code!="OK"}[1m])) by (grpc_service)
/ sum(rate(grpc_server_started_total{job="ecx-cloud-common-srv",grpc_type="unary"}[1m])) by (grpc_service) * 100.0 > 10
慢請求百分比
100.0 - (sum(rate(grpc_server_handling_seconds_bucket{job="ecx-cloud-common-srv",grpc_type="unary",le="0.25"}[5m])) by (grpc_service)
/ sum(rate(grpc_server_handling_seconds_count{job="ecx-cloud-common-srv",grpc_type="unary"}[5m])) by (grpc_service)) * 100.0 > 20