Prometheus 是一套开源的系统监控、报警、时间序列数据库的组合,最初有 SoundCloud 开发的,后来随着越来越多公司使用,于是便独立成开源项目。Prometheus 基本原理是通过 Http 协议周期性抓取被监控组件的状态,而输出这些被监控的组件的 Http 接口为 Exporter。PushGateway 作为 Prometheus 生态中的一个重要一员,它允许任何客户端向其 Push 符合规范的自定义监控指标,在结合 Prometheus 统一收集监控。
PushGateway 使用场景:
本次演示环境,我是在虚拟机上安装 Linux 系统来执行操作,以下是安装的软件及版本:
注意:这里为了快速方便启动 Prometheus、PushGateway 服务,我使用 Docker 方式启动,所以本机需要安装好 Docker 环境,这里忽略 Docker 的安装过程。其中 Prometheus 安装配置,可以参照之前文章 Prometheus 监控报警系统 AlertManager 之邮件告警,这里着重介绍一下如何启动并配置 PushGateway 并配置数据上报到 Prometheus。
PushGateway 安装很简单,可以使用二进制包解压安装服务,也可以使用 Docker 启动服务。
二进制包安装方式,直接从 官方 Github 下载最新二进制安装包,解压即可。
$ wget https://github.com/prometheus/pushgateway/releases/download/v1.0.0/pushgateway-1.0.0.linux-amd64.tar.gz
$ tar xzvf pushgateway-1.0.0.linux-amd64.tar.gz
$ mv pushgateway-1.0.0.linux-amd64 /usr/local/pushgateway
使用命令 ./pushgateway
命令即可启动服务,此时浏览器访问 http://
即可访问 UI 页面,只不过默认 Metrics 上没有任何数据展示,那是因为我们还没有往 PushGateway 上推送任何数据。
不过,PushGateway 服务本身是带了一些 Metrics 的,可以通过访问 http://
地址来获取,可以看到里边包含了 go、process 等相关的一些监控指标。
使用 Docker 方式安装启动就更简单了,直接获取最新版官方镜像 prom/pushgateway:latest
启动命令如下:
$ docker run -d -p 9091:9091 prom/PushGateway
启动完毕后,同上方法验证是否启动成功。这里为了方便演示,我采用 Docker 方式启动 PushGateway。
OK,现在 PushGateway 服务已经启动完毕,但是还没有跟 Prometheus 关联起来,我们需要的是通过 PushGateway 来上传自定义监控数据,然后通过 Prometheus 采集这些数据来进行监控。那么就需要将 PushGateway 添加到 Prometheus 目标任务中去,增加 prometheus.yml
配置如下:
...
- job_name: 'pushgateway'
static_configs:
- targets: ['172.30.12.167:9091']
labels:
instance: pushgateway
说明一下,这里采用 static_configs
静态配置方式,因为目前就一个 PushGateway,如果有多个可以考虑其他服务发现方式,来方便动态加载,具体可以参考 这里。配置完毕后,重启 Prometheus 服务,此时可以通过 Prometheus UI 页面的 Targets 下查看是否配置成功。
接下来,我们要 Push 数据到 PushGateway 中,可以通过其提供的 API 标准接口来添加,默认 URL 地址为:http://
,其中
是必填项,为 job 标签值,后边可以跟任意数量的标签对,一般我们会添加一个 instance/
实例名称标签,来方便区分各个指标。
接下来,可以 Push 一个简单的指标数据到 PushGateway 中测试一下。
$ echo "test_metric 123456" | curl --data-binary @- http://172.30.12.167:9091/metrics/job/test_job
执行完毕,刷新一下 PushGateway UI 页面,此时就能看到刚添加的 test_metric
指标数据了。
不过我们会发现,除了 test_metric
外,同时还新增了 push_time_seconds
和 push_failure_time_seconds
两个指标,这两个是 PushGateway 系统自动生成的相关指标。此时,我们在 Prometheus UI 页面上 Graph 页面可以查询的到该指标了。
这里要着重提一下的是,上图中 test_metric
我们查询出来的结果为 test_metric{exported_job="test_job",instance="pushgateway",job="pushgateway"}
,眼尖的会发现这里头好像不太对劲,刚刚提交的指标所属 job 名称为 test_job
,为啥显示的为 exported_job="test_job"
,而 job 显示为 job="pushgateway"
,这显然不太正确,那这是因为啥?其实是因为 Prometheus 配置中的一个参数 honor_labels
(默认为 false
)决定的,我们不妨再 Push 一个数据,来演示下添加 honor_labels: true
参数前后的变化。
这次,我们 Push 一个复杂一些的,一次写入多个指标,而且每个指标添加 TYPE
及 HELP
说明。
$ cat <<EOF | curl --data-binary @- http://172.30.12.167:9091/metrics/job/test_job/instance/test_instance
# TYPE test_metrics counter
test_metrics{label="app1",name="demo"} 100.00
# TYPE another_test_metrics gauge
# HELP another_test_metrics Just an example.
another_test_metrics 123.45
EOF
添加完毕,再刷新一下 PushGateway UI 页面,可以看到添加的数据了。
从上图可以看出,/metrics/job/test_job
和 metrics/job/test_job/instance/test_instance
虽然它们都属于 test_job
,但是它们属于两个指标值,因为 instance 对二者做了区分。此时我们访问 Prometheus UI 页面上 Graph 页面查询该指标。
依旧有问题,那么修改一下 prometheus.yaml
,增加 honor_labels: true
参数配置如下:
...
- job_name: 'pushgateway'
honor_labels: true
static_configs:
- targets: ['172.30.12.167:9091']
labels:
instance: pushgateway
重启 Prometheus,稍等一会,等到 Prometheus 采集到数据后,我们再访问 Prometheus UI 页面上 Graph 页面查询该指标。
此时,可以看到能够正确匹配到 Push 的指标值对应到 job 和 instance 上了。这里说明一下 honor_labels
的作用:因为 Prometheus 配置 PushGateway 的时候,也会指定 job 和 instance,但是它只表示 PushGateway 实例本身,不能真正表达收集数据的含义。所以配置 PushGateway 需要添加 honor_labels:true
参数,避免收集数据本身的 job 和 instance 被覆盖。详细可参考 这里 官网文档对该参数的说明。
上边我们 Push 指标数据是通过命令行追加方式,少量数据还凑合,如果需要 Push 的数据比较大时,就不太方便了,这里我们也可以通过将指标数据写入到文件,然后将文件内容提交,也可以正常添加到 PushGateway。新建一个指标数据文件 pgdata.txt
如下:
$ vim pgdata.txt
# TYPE http_request_total counter
# HELP http_request_total get interface request count with different code.
http_request_total{code="200",interface="/v1/save"} 276
http_request_total{code="404",interface="/v1/delete"} 0
http_request_total{code="500",interface="/v1/save"} 1
# TYPE http_request_time gauge
# HELP http_request_time get core interface http request time.
http_request_time{code="200",interface="/v1/core"} 0.122
然后执行如下命令,将数据 Push 上去。
curl -XPOST --data-binary @pgdata.txt http://172.30.12.167:9091/metrics/job/app/instance/app-172.30.0.0
执行完毕,在 PushGateway UI 页面同样能够查询的到。
最后,如果要删除某一个指标,同样可以通过 API 方式触发删除。例如删除 job="test_job"
组下的所有指标值,可以执行如下命令:
$ curl -X DELETE http://172.30.12.167:9091/metrics/job/test_job
注意:删除 job="test_job"
组下的所有指标值,不包括 {job="test_job", instance="test_instance"}
中的指标值,虽然它们的 job 名称都为 test_job
。如果想删除该指标值,那么需要执行如下命令:
curl -X DELETE http://172.30.12.167:9091/metrics/job/test_job/instance/test_instance
同样,我们也可以在 PushGateway UI 页面指定指标记录后边,点击 Delete Group
按钮来删除,这里就不在演示了。
通过 Client SDK 推送 metric 信息到 PushGateway,官方示例中支持 python、java、go 等不同语言类型 client,这里我以 java 语言为例,来演示下如何 Push 数据到 Pushgateway 中。
首先,pom.xml
中添加 simpleclient_pushgateway
依赖包。
<dependency>
<groupId>io.prometheusgroupId>
<artifactId>simpleclient_pushgatewayartifactId>
<version>0.7.0version>
dependency>
编写一个简单 demo 如下:
public static void main(String[] args) {
try{
String url = "172.30.12.167:9091";
CollectorRegistry registry = new CollectorRegistry();
Gauge guage = Gauge.build("my_custom_metric", "This is my custom metric.").create();
guage.set(23.12);
guage.register(registry);
PushGateway pg = new PushGateway(url);
Map<String, String> groupingKey = new HashMap<String, String>();
groupingKey.put("instance", "my_instance");
pg.pushAdd(registry, "my_job", groupingKey);
} catch (Exception e){
e.printStackTrace();
}
}
执行完毕后,访问一下 Pushgateway UI 页面,能够查询的到该指标。
上边列子比较简单,咱们在来一个稍微负载一些的,指定多个 label 标签组的指标。
public static void main(String[] args) {
try{
String url = "172.30.12.167:9091";
CollectorRegistry registry = new CollectorRegistry();
Gauge guage = Gauge.build("my_custom_metric", "This is my custom metric.").labelNames("app", "date").create();
String date = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss").format(new Date());
guage.labels("my-pushgateway-test-0", date).set(25);
guage.labels("my-pushgateway-test-1", date).dec();
guage.labels("my-pushgateway-test-2", date).dec(2);
guage.labels("my-pushgateway-test-3", date).inc();
guage.labels("my-pushgateway-test-4", date).inc(5);
guage.register(registry);
PushGateway pg = new PushGateway(url);
Map<String, String> groupingKey = new HashMap<String, String>();
groupingKey.put("instance", "my_instance");
pg.pushAdd(registry, "my_job", groupingKey);
} catch (Exception e){
e.printStackTrace();
}
}
同样,在 Pushgateway UI 页面,也能够查询的到该指标。
指标值只能是数字类型,非数字类型报错。
$ echo "test_metric 12.34.56ff" | curl --data-binary @- http://172.30.12.167:9091/metrics/job/test_job_1
text format parsing error in line 1: expected float as value, got "12.34.56ff"
指标值支持最大长度为 16 位,超过16 位后默认置为 0
$ echo "test_metric 1234567898765432123456789" | curl --data-binary @- http://172.30.12.167:9091/metrics/job/test_job_2
# 实际获取值
test_metric{job="test_job_2"} 1234567898765432200000000
PushGateway 数据持久化操作
默认 PushGateway 不做数据持久化操作,当 PushGateway 重启或者异常挂掉,导致数据的丢失,我们可以通过启动时添加 -persistence.file
和 -persistence.interval
参数来持久化数据。-persistence.file
表示本地持久化的文件,将 Push 的指标数据持久化保存到指定文件,-persistence.interval
表示本地持久化的指标数据保留时间,若设置为 5m,则表示 5 分钟后将删除存储的指标数据。
$ docker run -d -p 9091:9091 prom/pushgateway "-persistence.file=pg_file –persistence.interval=5m"
PushGateway 推送及 Prometheus 拉取时间设置
Prometheus 每次从 PushGateway 拉取的数据,并不是拉取周期内用户推送上来的所有数据,而是最后一次 Push 到 PushGateway 上的数据,所以推荐设置推送时间小于或等于 Prometheus 拉取的时间,这样保证每次拉取的数据是最新 Push 上来的。
参考资料