prometheus 工作原理

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

1. 服务注册

被监控服务在 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,演示下,百度了一下,这里可能是数据格式不统一导致。

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

2. 配置更新

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

第一步:首先要保证启动 Prometheus 的时候带上启动参数:--web.enable-lifecycle

prometheus --config.file=/usr/local/etc/prometheus.yml --web.enable-lifecycle

​第二步:去更新我们的 Prometheus 配置。

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

curl -v --request POST 'http://localhost:9090/-/reload'

原理:

Prometheus 在 web 模块中,注册了一个 handler:

通过 h.reload 这个 handler 方法实现:这个 handler 就是往一个 channle 中发送一个信号:

func (h *Handler) reload(w http.ResponseWriter, r *http.Request) {   
rc := make(chan error) h.reloadCh <- rc // 发送一个信号到channe了中
if err := <-rc; err != nil {
http.Error(w, fmt.Sprintf("failed to reload config: %s", err), http.StatusInternalServerError)
}
}

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

​case rc := <-webHandler.Reload():   
if err := reloadConfig(cfg.configFile, cfg.enableExpandExternalLabels, cfg.tsdb.EnableExemplarStorage, logger, noStepSubqueryInterval, reloaders...); err != nil {
level.Error(logger).Log("msg", "Error reloading config", "err", err)
rc <- err
} else {
rc <- nil
}

3. 指标抓取和存储

Prometheus 对指标的抓取采取主动 Pull 的方式,即周期性的请求被监控服务暴露的 metrics 接口或者是 PushGateway,从而获取到 Metrics 指标,默认时间是 15s 抓取一次,配置项如下:

​抓取到的指标会被以时间序列的形式保存在内存中,并且定时刷到磁盘上,默认是两个小时回刷一次。并且为了防止 Prometheus 发生崩溃或重启时能够恢复数据,Prometheus 也提供了类似 MySQL 中 binlog 一样的预写日志,当 Prometheus 崩溃重启时,会读这个预写日志来恢复数据。

什么是指标(metrics)?用外行的话来说,指标是数字测量,时间序列意味着随着时间的推移记录变化。用户想要测量的内容因应用程序而异。对于 Web 服务器,它可能是请求时间,对于数据库,它可能是活 ...