监控神器:Prometheus 轻松入门,真香!(上篇)

导语 :Prometheus是一个开源的完整监控解决方案,本文将从指标抓取到查询及可视化展示,以及最后的监控告警,对Prometheus做一个基本的认识。

一、简介

Prometheus是古希腊神话里泰坦族的一名神明,名字的意思是“先见之明”,下图中是Prometheus被宙斯惩罚,饱受肝脏日食夜长之苦。

下面就是我们CRUD Boy所了解的Prometheus,下面是其官网封面图引导语: From metrics to insight ,从指标到洞察力,通过指标去洞察你的系统,为我们的系统提供指标收集和监控的开源解决方案。

也就是说,Prometheus是一个数据监控的解决方案,让我们能随时掌握系统运行的状态,快速定位问题和排除故障。

Prometheus发展速度很快,12年开发完成,16年加入CNCF,成为继K8s 之后第二个CNCF托管的项目,目前Github 42k的?,而且社区很活跃,维护频率很高,基本稳定在1个月1个小版本的迭代速度。

二、整体生态

Prometheus提供了从指标暴露,到指标抓取、存储和可视化,以及最后的监控告警等一系列组件。

(一)指标暴露

每一个被Prometheus监控的服务都是一个Job,Prometheus为这些Job 提供了官方的SDK ,利用这个SDK可以自定义并导出自己的业务指标,也可以使用Prometheus官方提供的各种常用组件和中间件的Exporter(比如常用的MySQL,Consul等等)。

对于短时间执行的脚本任务或者不好直接 Pull指标的服务,Prometheus提供了PushGateWay网关给这些任务将服务指标主动推Push到网关,Prometheus再从这个网关里Pull指标。

(二)指标抓取

上面提到了Push和Pull,其实这是两种指标抓取模型。

  • Pull模型: 监控服务主动拉取被监控服务的指标。

被监控服务一般通过主动暴露 metrics 端口或者通过 Exporter 的方式暴露指标,监控服务依赖服务发现模块发现被监控服务,从而去定期的抓取指标。


  • Push模型: 被监控服务主动将指标推送到监控服务,可能需要对指标做协议适配,必须得符合监控服务要求的指标格式。

对于 Prometheus中的指标抓取,采用的是Pull模型,默认是一分钟去拉取一次指标,通过 Prometheus.yaml配置文件中的 scrape_interval配置项配置, Prometheus对外都是用的Pull模型,一个是 Pull Exporter的暴露的指标,一个是 Pull PushGateway暴露的指标。

(三)指标存储和查询

指标抓取后会存储在内置的时序数据库中, Prometheus也提供了PromQL 查询语言给我们做指标的查询,我们可以在 Prometheus的WebUI上通过  PromQL,可视化查询我们的指标,也可以很方便的接入第三方的可视化工具,例如 grafana

(四)监控告警

prometheus提供了 alertmanageer基于promql来做系统的监控告警,当promql查询出来的指标超过我们定义的阈值时, prometheus会发送一条告警信息到 alertmanager,manager会将告警下发到配置好的邮箱或者微信。

三、工作原理

Prometheus的从被监控服务的注册到指标抓取到指标查询的流程分为五个步骤:

(一)服务注册

被监控服务在 Prometheus中是一个Job存在,被监控服务的所有实例在  Prometheus中是一个target的存在,所以被监控服务的注册就是在  Prometheus中注册一个Job和其所有的target,这个注册分为: 静态注册和动态注册

静态注册: 静态的将服务的IP和抓取指标的端口号配置在 Prometheus yaml文件的 scrape_configs配置下:

以上就是注册了一个名为 prometheus 的服务,这个服务下有一个实例,暴露的抓取地址是 localhost:9090

动态注册: 动态注册就是在 Prometheus yaml文件的 scrape_configs配置下配置服务发现的地址和服务名, Prometheus会去该地址,根据你提供的服务名动态发现实例列表,在 Prometheus中,支持consul,DNS,文件,K8s等多种服务发现机制。基于consul的服务发现: 我们consul的地址就是: localhost:8500 ,服务名是 node_exporter ,在这个服务下有一个 exporter 实例: localhost:9600

注意:如果是动态注册,最好加上这两配置,静态注册指标拉取的路径会默认的帮我们指定为  metrics_path:/metrics,所以如果暴露的指标抓取路径不同或者是动态的服务注册,最好加上这两个配置。

不然会报错 “INVALID“ is not a valid start token,演示下,百度了一下,这里可能是数据格式不统一导致。

最后可以在webUI中查看发现的实例:

目前, Prometheus 支持多达二十多种服务发现协议:

(二)配置更新

在更新完 Prometheus的配置文件后,我们需要更新我们的配置到程序内存里,这里的更新方式有两种,第一种简单粗暴,就是重启 Prometheus,第二种是动态更新的方式。如何实现动态的更新Prometheus配置。

第一步:首先要保证启动 Prometheus的时候带上启动参数: --web.enable-lifecycle 第二步:去更新我们的 Prometheus 配置:

第三步:更新完配置后,我们可以通过Post请求的方式,动态更新配置:

原理:

Prometheus在web模块中,注册了一个 handler 通过 h.reload 这个 handler 方法实现:这个 handler 就是往一个 channle 中发送一个信号:


在main函数中会去监听这个channel,只要有监听到信号,就会做配置的reload,重新将新配置加载到内存中。

(三)指标抓取和存储

Prometheus对指标的抓取采取主动Pull的方式,即周期性的请求被监控服务暴露的 metrics接口或者是 PushGateway,从而获取到 Metrics指标,默认时间是15s抓取一次,配置项如下: 抓取到的指标会被以时间序列的形式保存在内存中,并且定时刷到磁盘上,默认是两个小时回刷一次。并且为了防止 Prometheus  发生崩溃或重启时能够恢复数据, Prometheus 也提供了类似MySQL中binlog一样的预写日志,当 Prometheus 崩溃重启时,会读这个预写日志来恢复数据。

四、Metric指标

(一)数据模型

Prometheus采集的所有指标都是以时间序列的形式进行存储,每一个时间序列有三部分组成:

  • 指标名和指标标签集合: metric_name{,....},指标名:表示这个指标是监控哪一方面的状态,比如 http_request_total表示:请求数量;指标标签,描述这个指标有哪些维度,比如 http_request_total这个指标,有请求状态码 code= 200/400/500,请求方式: method=get/post等,实际上指标名称实际上是以标签的形式保存,这个标签是name,即: name=

  • 时间戳:描述当前时间序列的时间,单位:毫秒。

  • 样本值:当前监控指标的具体数值,比如 http_request_total的值就是请求数是多少。

可以通过查看 Prometheusmetrics接口查看所有上报的指标:

所有的指标也都是通过如下所示的格式来标识的:

(二)指标类型

Prometheus底层存储上其实并没有对指标做类型的区分,都是以时间序列的形式存储,但是为了方便用户的使用和理解不同监控指标之间的差异, Prometheus定义了4种不同的指标类型:计数器 counter,仪表盘 gauge,直方图 histogram,摘要 summary

Counter计数器:

Counter类型和redis的自增命令一样,只增不减,通过Counter指标可以统计Http请求数量,请求错误数,接口调用次数等单调递增的数据。同时可以结合 increase和rate等函数统计变化速率,后续我们会提到这些内置函数。

Gauge仪表盘:

Counter不同,Gauge是可增可减的,可以反映一些动态变化的数据,例如当前内存占用,CPU利用,Gc次数等动态可上升可下降的数据,在 Prometheus上通过Gauge,可以不用经过内置函数直观的反映数据的变化情况,如下图表示堆可分配的空间大小:

上面两种是数值指标,代表数据的变化情况, HistogramSummary是统计类型的指标,表示数据的分布情况。

Histogram直方图:

Histogram是一种直方图类型,可以观察到指标在各个不同的区间范围的分布情况,如下图所示:可以观察到请求耗时在各个桶的分布。

有一点要注意的是, Histogram是累计直方图,即每一个桶的是只有上区间,例如下图表示小于0.1毫秒( le=“0.1”)的请求数量是18173个,小于 0.2毫秒( le=“0.2”)的请求是 18182 个,在 le=“0.2”这个桶中是包含了  le=“0.1”这个桶的数据,如果我们要拿到0.1毫秒到0.2毫秒的请求数量,可以通过两个桶想减得到。 在直方图中,还可以通过 histogram_quantile 函数求出百分位数,比如 P50,P90,P99等数据。

Summary摘要

Summary也是用来做统计分析的,和 Histogram区别在于, Summary直接存储的就是百分位数,如下所示:可以直观的观察到样本的中位数,P90和P99。 Summary 的百分位数是客户端计算好直接让 Prometheus 抓取的,不需要  Prometheus 计算,直方图是通过内置函数 histogram_quantile 在  Prometheus 服务端计算求出。

(三)指标导出

指标导出有两种方式,一种是使用 Prometheus社区提供的定制好的  Exporter对一些组件诸如MySQL,Kafka等的指标作导出,也可以利用社区提供的 Client来自定义指标导出。

自定义 Prometheus exporter 访问:, 即可看到导出的指标,这里我们没有自定义任何的指标,但是能看到一些内置的Go的运行时指标和promhttp相关的指标,这个Client默认为我们暴露的指标, go_ :以  go_  为前缀的指标是关于Go运行时相关的指标,比如垃圾回收时间、 goroutine  数量等,这些都是Go客户端库特有的,其他语言的客户端库可能会暴露各自语言的其他运行时指标。 promhttp_ :来自 promhttp 工具包的相关指标,用于跟踪对指标请求的处理。

添加自定义指标:

运行:

模拟下在业务中上报接口请求量: main.go: 一开始启动时,指标counter是0:

调用: /counter 接口后,指标数据发生了变化,这样就可以简单实现了接口请求数的统计:


对于其他指标定义方式是一样的:

上面的指标都是没有设置标签的,我们一般的指标都是带有标签的,如何设置指标的标签呢?

如果我要设置带标签的counter类型指标,只需要将原来的 NewCounter方法替换为 NewCounterVec方法即可,并且传入标签集合。

其他同理。

监控神器:Prometheus 轻松入门,真香!(下篇)

请使用浏览器的分享功能分享到微信等