指标采集方法
当前,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