Prometheus 监控业务指标
可观测性
-
Lgging,展现的是应用运行而产生的事件或者程序在执行的过程中间产生的一些日志,可以详细解释系统的运行状态,但是存储和查询需要消耗大量的资源。所以往往使用过滤器减少数据量。
-
Metrics,是一种聚合数值,存储空间很小,可以观察系统的状态和趋势,但对于问题定位缺乏细节展示。这个时候使用等高线指标等多维数据结构来增强对于细节的表现力。例如统计一个服务的 TBS 的正确率、成功率、流量等,这是常见的针对单个指标或者某一个数据库的。
-
Tracing,面向的是请求,可以轻松分析出请求中异常点,但与 logging 有相同的问题就是资源消耗较大。通常也需要通过采样的方式减少数据量。比如一次请求的范围,也就是从浏览器或者手机端发起的任何一次调用,一个流程化的东西,我们需要轨迹去追踪。
指标
指标定义
在形式上,所有的指标(Metric)都通过如下格式标示:
<metric name>{<label name>=<label value>, ...}
指标的名称(metric name)可以反映被监控样本的含义(比如,
http_request_total
– 表示当前系统接收到的HTTP请求总量)。指标名称只能由ASCII字符、数字、下划线以及冒号组成并必须符合正则表达式[a-zA-Z_:][a-zA-Z0-9_:]*
。标签(label)反映了当前样本的特征维度,通过这些维度Prometheus可以对样本数据进行过滤,聚合等。标签的名称只能由ASCII字符、数字以及下划线组成并满足正则表达式 [a-zA-Z_][a-zA-Z0-9_]*
。指标类型
Prometheus定义了4种不同的指标类型(metric type):Counter(计数器)、Gauge(仪表盘)、Histogram(直方图)、Summary(摘要)。 Counter
Counter类型的指标其工作方式和计数器一样,只增不减(除非系统发生重置)。常见的监控指标,如 http_requests_total
,node_cpu
都是 Counter 类型的监控指标。一般在定义Counter类型指标的名称时推荐使用_total
作为后缀。通过 counter 指标我们可以和容易的了解某个事件产生的速率变化。
例如,通过
rate()
函数获取HTTP请求量的增长率:rate(http_requests_total[5m])
Gauge
Gauge类型的指标侧重于反应系统的当前状态。因此这类指标的样本数据可增可减。常见指标如: node_memory_MemFree
(主机当前空闲的内容大小)、node_memory_MemAvailable
(可用内存大小)都是Gauge类型的监控指标。通过Gauge指标,我们可以直接查看系统的当前状态 node_memory_MemFree
Summary
Summary 主用用于统计和分析样本的分布情况。比如某 Http 请求的响应时间大多数都在 100 ms 内,而个别请求的响应时间需要 5s,那么这中情况下统计指标的平均值就不能反映出真实情况。而如果通过 Summary 指标我们能立马看响应时间的9分位数,这样的指标才是有意义的。 例如
# HELP go_gc_duration_seconds A summary of the pause duration of garbage collection cycles.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 3.98e-05
go_gc_duration_seconds{quantile="0.25"} 5.31e-05
go_gc_duration_seconds{quantile="0.5"} 6.77e-05
go_gc_duration_seconds{quantile="0.75"} 0.0001428
go_gc_duration_seconds{quantile="1"} 0.0008099
go_gc_duration_seconds_sum 0.0114183
go_gc_duration_seconds_count 85
Histogram
Histogram 类型的指标同样用于统计和样本分析。与 Summary 类型的指标相似之处在于 Histogram 类型的样本同样会反应当前指标的记录的总数(以 _count
作为后缀)以及其值的总量(以_sum
作为后缀)。不同在于 Histogram 指标直接反应了在不同区间内样本的个数,区间通过标签len进行定义。同时对于Histogram的指标,可以通过histogram_quantile()
函数计算出其值的分位数。例如 # HELP prometheus_http_response_size_bytes Histogram of response size for HTTP requests.
# TYPE prometheus_http_response_size_bytes histogram
prometheus_http_response_size_bytes_bucket{handler="/",le="100"} 1
prometheus_http_response_size_bytes_bucket{handler="/",le="1000"} 1
prometheus_http_response_size_bytes_bucket{handler="/",le="10000"} 1
prometheus_http_response_size_bytes_bucket{handler="/",le="100000"} 1
prometheus_http_response_size_bytes_bucket{handler="/",le="1e+06"} 1
prometheus_http_response_size_bytes_bucket{handler="/",le="+Inf"} 1
prometheus_http_response_size_bytes_sum{handler="/"} 29
prometheus_http_response_size_bytes_count{handler="/"} 1
应用指标监控
暴露指标
Prometheus 最常用的方式是通过 pull 去抓取 metrics。所以我们首先在服务通过 /metrics
接口暴露指标,这样 Promethues server 就能通过 http 请求抓取到我们的业务指标。接口示例
server := gin.New()
server.Use(middlewares.AccessLogger(), middlewares.Metric(), gin.Recovery())
server.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{ "message": "ok",
})
})
server.GET("/metrics", Monitor)func Monitor(c *gin.Context) {
h := promhttp.Handler()
h.ServeHTTP(c.Writer, c.Request)
}
定义指标
为了方便理解,这里选取了三种类型和两种业务场景的指标
示例var (
//HTTPReqDuration metric:http_request_duration_seconds
HTTPReqDuration *prometheus.HistogramVec
//HTTPReqTotal metric:http_request_total
HTTPReqTotal *prometheus.CounterVec
// TaskRunning metric:task_running
TaskRunning *prometheus.GaugeVec
)
func init() {
// 监控接口请求耗时
// 指标类型是 Histogram
HTTPReqDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "http request latencies in seconds",
Buckets: nil,
}, []string{"method", "path"})
// "method"、"path" 是 label
// 监控接口请求次数
// 指标类型是 Counter
HTTPReqTotal = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "http_requests_total",
Help: "total number of http requests",
}, []string{"method", "path", "status"}) // "method"、"path"、"status" 是 label
// 监控当前在执行的 task 数量
// 监控类型是 Gauge
TaskRunning = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "task_running",
Help: "current count of running task",
}, []string{"type", "state"})
// "type"、"state" 是 label
prometheus.MustRegister(
HTTPReqDuration,
HTTPReqTotal,
TaskRunning,
)
}
通过上述的代码我们就定义并且注册了我们的想要监控的指标。
生成指标
示例
start := time.Now()
c.Next()
duration := float64(time.Since(start)) / float64(time.Second)
path := c.Request.URL.Path
// 请求数加1
controllers.HTTPReqTotal.With(prometheus.Labels{
"method": c.Request.Method,
"path": path,
"status": strconv.Itoa(c.Writer.Status()),
}).Inc()
// 记录本次请求处理时间
controllers.HTTPReqDuration.With(prometheus.Labels{
"method": c.Request.Method,
"path": path,
}).Observe(duration)
// 模拟新建任务
controllers.TaskRunning.With(prometheus.Labels{
"type": shuffle([]string{"video", "audio"}),
"state": shuffle([]string{"process", "queue"}),
}).Inc()
// 模拟任务完成
controllers.TaskRunning.With(prometheus.Labels{
"type": shuffle([]string{"video", "audio"}),
"state": shuffle([]string{"process", "queue"}),
}).Dec()
抓取指标
Promethues 抓取 target 配置
# 抓取间隔
scrape_interval: 5s
# 目标
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['prometheus:9090']
- job_name: 'local-service'
metrics_path: /metrics
static_configs:
- targets: ['host.docker.internal:8000']
在实际应用中静态配置 target 地址不太适用,在 k8s 下 Promethues通过与 Kubernetes API 集成目前主要支持5种服务发现模式,分别是:Node、Service、Pod、Endpoints、Ingress。 指标展示如下图: 来源:https://www.lxkaka.wang/app-metrics/ 10月26-27日,GOPS 全球运维大会 2023 · 上海站,来自腾讯、阿里、字节、农行、交行、申万宏源等近 90 位大咖齐聚 GOPS,为您分享自动化、DevOps、AIOps、SRE 等您关心的运维话题,还有大型企业数字化转型案例等您来!
点击阅读原文,访问大会官网 近期好文: 一次 Jedis 参数异常引发服务雪崩,结局你绝对想不到?
“高效运维”公众号诚邀广大技术人员投稿
投稿邮箱:jiachen@greatops.net,或添加联系人微信:greatops1118。 点个“在看”,一年不宕机