监控利器 prometheus 使用步骤

2022-11-30 15:17:33 浏览数 (1)

1. 监控

完善的监控和合理的指标采集方便我们去观察线上的健康情况, 更好的预测和处理问题.

监控我们可以分为白盒监控和黑盒监控, 那它们具体表示什么意思呢?

⿊盒监控:站在⽤户的⻆度看到的东⻄。⽹站不能打开,⽹站打开的⽐较慢, 监控机器的磁盘空间、内存占用、链接句柄等信息, 更多的是全局表象的信息, 一般不容易定位到具体问题.

⽩盒监控:监控服务内部自定义的数据,比如最近sql耗时情况、redis链接情况、服务一些业务方面数据等, 完善的白盒监控能让我们清楚了解到服务运行中的情况, 成为定位问题的根因.

监控工具众多, 在当今云原生时代提起监控自然少不了 prometheus.

2. 为什么选择 prometheus

黑盒监控方面 prometheus 提供了丰富的node_export, 不仅有拿来即用的机器监控基础指标, 还有丰富的mysql、memcache等服务的export可以直接使用.

在白盒监控方面 prometheus 提供了各类语言的包, 可以非常方便集成到项目里面, 例如 go 语言默认带有 goroutine、thread、gc、heap 等服务指标监控, 还方便自己定义业务指标, 集成到监控体系中去, 下文我们将会有此案例展示.

prometheus 背景

Prometheus是一个开源系统监控和警报工具包,最初在 SoundCloud构建。自 2012 年成立以来,许多公司和组织都采用了 Prometheus。它现在是一个独立的开源项目,独立于任何公司维护。为了强调这一点,并明确项目的治理结构,Prometheus 于 2016 年加入 云原生计算基金会,成为继Kubernetes之后的第二个托管项目.

更多详细资料可参考最下方给出的官方文档

我们来看下具体 prometheus 是怎么工作的?

image.png

1.采集部分

左侧部分是采集部分, prometheus 采集数据全部都是通过 http pull 的模式来获取服务指标数据的.

对于一些临时性job等场景, 则提供了Pushgateway组件, 将指标信息push到gateway上, prometheus 通过拉取 gateway 获取指标数据.

关于 pull 和 push 的争论有很多, 无疑pull模式对于双方来说, 对于业务侵入性和接入复杂度都是最小的, 感兴趣读者可查阅下方总结链接

2. prometheus server

prometheus 怎么知道要去拉取哪些机器地址指标呢?

Time Series Database (TSDB) 时序数据库, 负责存储我们的指标数据.

Retrieval 通过服务发现或文件配置获取到目标地址进行 pull 抓取指标数据, 写入TSDB.

HTTP server 提供访问 TSDB 数据的接口, 用于与外部交互

3. PromQL

PromQL(Prometheus Query Language)是 Prometheus 内置的数据查询语言,它能实现对事件序列数据的查询、聚合、逻辑运算等处理, 功能非常强大

PromQL 广泛存在于以 Prometheus 为核心的监控体系中。所以需要用到数据筛选的地方,就会用到 PromQL。例如:监控指标的设置、报警指标的设置等等

例如:

代码语言:javascript复制
// 过去五分钟平均每秒增长率
rate(http_requests_total{job="api-server"}[5m])

// 过去五分钟内 HTTP 请求数
increase(http_requests_total{job="api-server"}[5m])

//计算过去十分钟内请求持续时间的 90 百分位
histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))

值得一提的是不仅可以使用自己的 prometheus 查询界面, 并且还很好的配合 grafana 完成图表配置.

4. Alertmanager

报警一直是整个监控系统中的重要组成部分,Prometheus监控系统中,采集与警报是分离的.

Alertmanager模块负责配置告警的配置

3. prometheus Metrics 指标类型

3.1 counter 单调递增

通常 counter 用来表示服务的请求数、服务错误数、累加值数据, 通常结合PromQL的rate、increase等函数配置.

对应接口:

代码语言:javascript复制
type Counter interface {
   // Inc increments the counter by 1. Use Add to increment it by arbitrary
   // non-negative values.
   Inc()
   // Add adds the given value to the counter. It panics if the value is <
   // 0.
   Add(float64)
}

我们可以看到counter类型的, 只提供了累加值功能

案例: 接口请求数统计

代码语言:javascript复制
_metricServerErrorRequest := prometheus.NewCounterVec(prometheus.CounterOpts{
   Name: "lib_server_request_error_total",
   Help: "The total number of http or grpc request error",
}, []string{"kind", "action"})

// kind=http action=/activity/health 请求数 1
_metricServerErrorRequest.WithLabelValues("http", "/activity/health").Inc()

3.2 Gauge 可增可减

Guage 类型代表⼀种样本数据可以任意变化的指标,即可增可减. 例如我们统计的当前协程数、线程数、CPU占用率等.

对应接口:

代码语言:javascript复制
type Gauge interface {
   // Set sets the Gauge to an arbitrary value.
   Set(float64)
   // Inc increments the Gauge by 1. Use Add to increment it by arbitrary
   // values.
   Inc()
   // Dec decrements the Gauge by 1. Use Sub to decrement it by arbitrary
   // values.
   Dec()
   // Add adds the given value to the Gauge. (The value can be negative,
   // resulting in a decrease of the Gauge.)
   Add(float64)
   // Sub subtracts the given value from the Gauge. (The value can be
   // negative, resulting in an increase of the Gauge.)
   Sub(float64)

   // SetToCurrentTime sets the Gauge to the current Unix time in seconds.
   SetToCurrentTime()
}

案例: 当前系统并发数

代码语言:javascript复制
inFlightGauge := prometheus.NewGauge(prometheus.GaugeOpts{
   Name: "client_in_flight_requests",
   Help: "A gauge of in-flight requests for the wrapped client.",
})

//累加1
inFlightGauge.Inc()

// dosomething

//减少1
inFlightGauge.Sub(1)

结构类似下图, go_threads 表示当前的线程数

image.png

3.3 Histogarm 直方图

服务请求耗时通常具有长尾问题, 如果我们更想关注有多少请求是在50ms内完成的, 有多少是在100ms完成的, 则需要用到分桶, Histogarm 或 Summary 就是做这个事情的.

代码语言:javascript复制
type Histogram interface {
   // Observe adds a single observation to the histogram. Observations are
   // usually positive or zero. Negative observations are accepted but
   // prevent current versions of Prometheus from properly detecting
   // counter resets in the sum of observations. See
   // https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
   // for details.
   Observe(float64)
}

案例: 接口耗时统计

代码语言:javascript复制
_metricUrlDuration := prometheus.NewHistogramVec(prometheus.HistogramOpts{
   Name:    "lib_url_duration_ms",
   Help:    "server requests duration(ms).",
   Buckets: []float64{25, 50, 100, 200, 500, 1000},
}, []string{"action"})

// activity/health 接口耗时58ms
_metricUrlDuration.WithLabelValues("/activity/health").Observe(58)

结构类似下图 (action表示接口, le表示时间ms)

image.png

在使用此类型时, 要合理评估指标产生量和bucket区间, 如果不注意很可能一条配置成指数级扩增, 影响采集效率.

3.4 Summary 简化直方图

与 Histogram 类型类似, ⽤于表示⼀段时间内的数据采样结果(通常是请求持续时间或响应⼤⼩等), 但它直接 存储了分位数(通过客户端计算,然后展示出来), ⽽不是通过区间来计算.

代码语言:javascript复制
type Summary interface {
   // Observe adds a single observation to the summary. Observations are
   // usually positive or zero. Negative observations are accepted but
   // prevent current versions of Prometheus from properly detecting
   // counter resets in the sum of observations. See
   // https://prometheus.io/docs/practices/histograms/#count-and-sum-of-observations
   // for details.
   Observe(float64)
}

4. go项目如何引入prometheus

go 引入 prometheus 也非常简单,

4.1 第一步 引入系统自导指标

引入 github.com/prometheus/client_golang/prometheus/promhttp

代码语言:javascript复制
// ....
import "github.com/prometheus/client_golang/prometheus/promhttp"

// 默认已经包含了go的常用服务监控指标
srv.HandlePrefix("/metrics", promhttp.Handler())

默认prometheus会自动抓取 /metrics 路径, 只要网络是畅通的, 我们指标就自动被采集到 prometheus 上去了, 业务端不用感知任何 proemtheus 节点且对业务无影响, 这是 pull 模式最大的好处.

引入包后默认自带了 goroutine、heap、gc 等go应用的统计指标, 当然我们再延伸更希望定义一些指标.

第二步 加入自定义指标

代码语言:javascript复制
//服务请求耗时/总请求数
_metricUrlDuration := prometheus.NewHistogramVec(prometheus.HistogramOpts{
   Name:    "lib_url_duration_ms",
   Help:    "server requests duration(ms).",
   Buckets: []float64{25, 50, 100, 200, 500, 1000},
}, []string{"action"})

//服务异常数
_metricServerErrorRequest := prometheus.NewCounterVec(prometheus.CounterOpts{
   Name: "lib_server_request_error_total",
   Help: "The total number of http or grpc request error",
}, []string{"kind", "action"})

//sql请求耗时
_metricSqlDuration := prometheus.NewHistogramVec(prometheus.HistogramOpts{
   Name:    "lib_sql_duration_ms",
   Help:    "sql requests duration(ms).",
   Buckets: []float64{25, 50, 100, 200, 500},
}, []string{})

prometheus.MustRegister(_metricServerErrorRequest, _metricUrlDuration, _metricSqlDuration)

上面代码在指标类型展出那出现过, histogram 和 counter 类型的指标

第三步, 根据不同请求打点计数

可以在业务代码中使用定义好的 metric 对象打点计数.

代码语言:javascript复制
// 设置请求耗时58ms
_metricUrlDuration.WithLabelValues("/activity/health").Observe(58)

// activity/health 接口请求数量 1
_metricServerErrorRequest.WithLabelValues("http", "/activity/health").Inc()

最终效果图例:

image.png

image.png

image.png

5.参考

prometheus官方文档 https://prometheus.io/docs/introduction/overview/

中文文档 https://icloudnative.io/prometheus/

pull 和 push 模式的对比 https://developer.aliyun.com/article/786418

0 人点赞