Prometheus 4种 Metrics类型
Counter
表示收集的数据是按照某个趋势(增加/减少)一直变化的,我们往往用它记录服务请求总量、错误总数等。
例如 Prometheus server 中 http_requests_total, 表示 Prometheus 处理的 http 请求总数,我们可以使用 delta, 很容易得到任意区间数据的增量,这个会在 PromQL 一节中细讲。Gauge
表示搜集的数据是一个瞬时的值,与时间没有关系,可以任意变高变低,往往可以用来记录内存使用率、磁盘使用率等。Histogram
由 bucket, sum, count 组成,主要用于表示一段时间范围
内对数据进行采样(通常是请求持续时间或响应大小),并能够对其指定区间以及总数
进行统计,通常它采集的数据展示为直方图。Summary 和 Histogram 类似,由
{quantile="<φ>"}, sum, count 组成,主要用于表示一段时间内数据采样结果(通常是请求持续时间或响应大小),但它 直接存储
了 quantile 数据,而不是根据统计区间计算
出来的。
Histogram vs Summary
都包含 bucket, sum, count
Histogram 需要通过 bucket 计算 quantile, 而 Summary 直接存储了 quantile 的值。
Metrics,谷歌翻译就是度量的意思。当我们需要为某个系统某个服务做监控、做统计,就需要用到Metrics。
举个栗子,一个图片压缩服务:
每秒钟的请求数是多少(TPS)?
平均每个请求处理的时间?
请求处理的最长耗时?
等待处理的请求队列长度?
又或者一个缓存服务:
缓存的命中率?
平均查询缓存的时间?
基本上每一个服务、应用都需要做一个监控系统,这需要尽量以少量的代码,实现统计某类数据的功能。
Metric Registries
MetricRegistry类是Metrics的核心,它是存放应用中所有metrics的容器。也是我们使用 Metrics 库的起点。
MetricRegistry registry = new MetricRegistry();
每一个 metric 都有它独一无二的名字,Metrics 中使用句点名字,如 com.example.Queue.size。当你在 com.example.Queue 下有两个 metric 实例,可以指定地更具体:com.example.Queue.requests.size 和 com.example.Queue.response.size 。使用MetricRegistry类,可以非常方便地生成名字。
MetricRegistry.name(Queue.class, "requests", "size")
MetricRegistry.name(Queue.class, "responses", "size")
Metrics 数据展示
Metircs 提供了 Report 接口,用于展示 metrics 获取到的统计数据。metrics-core中主要实现了四种 reporter: JMX, console, SLF4J, 和 CSV。 在本文的例子中,我们使用 ConsoleReporter 。
五种 Metrics 类型
Gauges
最简单的度量指标,只有一个简单的返回值,例如,我们想衡量一个待处理队列中任务的个数,代码如下:
-- Gauges ------------------------------------------------
com.alibaba.wuchong.metrics.GaugeTest.queue.size
value = 6
其中第7行和第8行添加了ConsoleReporter,可以每秒钟将度量指标打印在屏幕上,理解起来会更清楚。
但是对于大多数队列数据结构,我们并不想简单地返回queue.size(),因为java.util和java.util.concurrent中实现的#size()方法很多都是 O(n) 的复杂度,这会影响 Gauge 的性能。
Counters
Counter 就是计数器,Counter 只是用 Gauge 封装了 AtomicLong 。我们可以使用如下的方法,使得获得队列大小更加高效。
-- Counters ----------------------------------------------
java.util.Queue.pending-jobs.size
count = 5
Meters
Meter度量一系列事件发生的速率(rate),例如TPS。Meters会统计最近1分钟,5分钟,15分钟,还有全部时间的速率。
-- Meters ------------------------------------------------
com.alibaba.wuchong.metrics.MeterTest.request.tps
count = 134
mean rate = 2.13 events/second
1-minute rate = 2.52 events/second
5-minute rate = 3.16 events/second
15-minute rate = 3.32 events/second
注:非常像 Unix 系统中 uptime 和 top 中的 load。
Histograms
Histogram统计数据的分布情况。比如最小值,最大值,中间值,还有中位数,75百分位, 90百分位, 95百分位, 98百分位, 99百分位, 和 99.9百分位的值(percentiles)。
比如request的大小的分布:
-- Histograms --------------------------------------------
java.util.Queue.queue.histogram
count = 56
min = 1122
max = 99650
mean = 48735.12
stddev = 28609.02
median = 49493.00
75% <= 72323.00
95% <= 90773.00
98% <= 94011.00
99% <= 99650.00
99.9% <= 99650.00
Timers
Timer其实是 Histogram 和 Meter 的结合, histogram 某部分代码/调用的耗时, meter统计TPS。
-- Timers ------------------------------------------------
com.alibaba.wuchong.metrics.TimerTest.get-latency
count = 38
mean rate = 1.90 calls/second
1-minute rate = 1.66 calls/second
5-minute rate = 1.61 calls/second
15-minute rate = 1.60 calls/second
min = 13.90 milliseconds
max = 988.71 milliseconds
mean = 519.21 milliseconds
stddev = 286.23 milliseconds
median = 553.84 milliseconds
75% <= 763.64 milliseconds
95% <= 943.27 milliseconds
98% <= 988.71 milliseconds
99% <= 988.71 milliseconds
99.9% <= 988.71 milliseconds
其他
初次之外,Metrics还提供了 HealthCheck 用来检测某个某个系统是否健康,例如数据库连接是否正常。还有Metrics Annotation,可以很方便地实现统计某个方法,某个值的数据。感兴趣的可以点进链接看看。
使用经验总结
一般情况下,当我们需要统计某个函数被调用的频率(TPS),会使用Meters。当我们需要统计某个函数的执行耗时时,会使用Histograms。当我们既要统计TPS又要统计耗时时,我们会使用Timers。
本文将介绍Prometheus下的四种基本数据结构,以及其使用场景。
上一篇文章中分享了在Kubernetes部署Prometheus的内容,Prometheus除了监控数据采集,存储,查询以外。也提供了非常方便的扩展接口,可以方便用户根据自己的业务实现自己的数据采集Exporter。 再实现自定义Exporter或者在现有应用上扩展API接口支持Prometheus采集数据之前,我们需要先了解一下Prometheus下的度量指标数据结构基本类型
Prometheus metric类型
Prometheus的Client Library提供度量的四种基本类型包括:Counter,Gauge,Histogram,Summary。当访问Exporter的/metrics API地址时我们可以看到类似于一下返回值,其中HELP用于说明度量类型,TYPE用于数据类型说明。
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 255.477922
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 312.0
需要注意的是,虽然Prometheus Client Library可以定义不同的数据类型,但是Prometheus Server在获取到这些监控数据后并没有使用它们的类型(Type)信息而直接将这些数据扁平处理,并且无区别的保存到时序数据库当中。 因此这四种数据类型主要是提供一些参考,用于不同的度量数据场景
Counter计数器
Counter类型,Counter类型好比计数器,用于统计类似于:CPU时间,API访问总次数,异常发生次数等等场景。这些指标的特点就是增加不减少。
Example: 容器CPU使用率
在使用cAdvisor采集容器数据时,我们会得到监控指标container_cpu_user_seconds_total,该指标的的数据类型为Counter用户反映当前容器在各个CPU内核上已经使用的CPU总时间。
通过Prometheus直接查询该指标我们会得到以下数据
container_cpu_usage_seconds_total{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",container_name="mysql",cpu="cpu03",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod74ab5e96_6209_11e7_9990_00163e122a49.slice/docker-fb332c4ede82562be6eaebe3eef6376d3f37b3402a7fd570c7c95f8963012c0b.scope",image="docker.io/mysql@sha256:d178dffba8d81afedc251498e227607934636e06228ac63d58b72f9e9ec271a6",instance="dev-4",job="kubernetes-nodes",kubernetes_io_hostname="dev-4",name="k8s_mysql_go-todo-mysql-3723120250-vf8wx_default_74ab5e96-6209-11e7-9990-00163e122a49_0",namespace="default",pod_name="go-todo-mysql-3723120250-vf8wx"}
container_cpu_usage_seconds_total{beta_kubernetes_io_arch="amd64",beta_kubernetes_io_os="linux",container_name="mysql",cpu="cpu01",id="/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod74ab5e96_6209_11e7_9990_00163e122a49.slice/docker-fb332c4ede82562be6eaebe3eef6376d3f37b3402a7fd570c7c95f8963012c0b.scope",image="docker.io/mysql@sha256:d178dffba8d81afedc251498e227607934636e06228ac63d58b72f9e9ec271a6",instance="dev-4",job="kubernetes-nodes",kubernetes_io_hostname="dev-4",name="k8s_mysql_go-todo-mysql-3723120250-vf8wx_default_74ab5e96-6209-11e7-9990-00163e122a49_0",namespace="default",pod_name="go-todo-mysql-3723120250-vf8wx"}
如果使用图形化查询我们可以看出
因此当我们需要统计容器CPU的使用率时,我们需要使用rate()函数计算该Counter在过去一段时间内在每一个时间序列上的每秒的平均增长率
rate(container_cpu_user_seconds_total[5m]) * 100
Gauge仪表盘
Gauge类型,英文直译的话叫“计量器”,但是和Counter的翻译太类似了,因此我个人更喜欢使用”仪表盘“这个称呼。仪表盘的特点就是数值是可以增加或者减少的。因此Gauge适合用于如:当前内存使用率,当前CPU使用率,当前温度,当前速度等等一系列的监控指标。
Example:主机负载信息
在使用NodeExporter时,指标node_load1可以反映当前主机的负载情况,而其类型则是Gauge,因此在查询主机负载变化时比较简单,直接使用node_load1即可查询出当前所有主机的负载情况
node_load1{app="node-exporter",instance="192.168.2.2:9100",job="kubernetes-service-endpoints",kubernetes_name="node-exporter",kubernetes_namespace="default",name="node-exporter",nodeIp="192.168.2.2:9100"}
node_load1{app="node-exporter",instance="192.168.2.3:9100",job="kubernetes-service-endpoints",kubernetes_name="node-exporter",kubernetes_namespace="default",name="node-exporter",nodeIp="192.168.2.3:9100"}
Histogram柱状图
Histogram这个比较直接柱状图图,更多的是用于统计一些数据分布的情况,用于计算在一定范围内的分布情况,同时还提供了度量指标值的总和。
Example:
以Kubernates的API Server度量指标apiserver_request_latencies为例,该指标反映了Kubernates的API请求响应延迟时间。该指标会在一次监控数据抓取过程中返回2中Metrics Key
apiserver_request_latencies_bucket
apiserver_request_latencies_count
apiserver_request_latencies_sum
apiserver_request_latencies_bucket反映在各个API响应延迟范围(le)内总数
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="+Inf",resource="podpresets",verb="WATCH"} 773
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="500000",resource="endpoints",verb="DELETE"} 85
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="1e+06",resource="configmaps",verb="PUT"} 1
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="1e+06",resource="daemonsets",verb="WATCHLIST"} 0
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="2e+06",resource="replicationcontrollers",verb="GET"} 6
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="125000",resource="deployments",verb="PATCH"} 12
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="+Inf",resource="configmaps",verb="DELETE"} 9
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="125000",resource="replicasets",verb="GET"} 1331
apiserver_request_latencies_bucket{instance="192.168.2.2:6443",job="kubernetes-apiservers",le="+Inf",resource="persistentvolumes",verb="LIST"} 3
apiserver_request_latencies_count反映对各个资源API的请求次数
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="replicasets",verb="PUT"} 3030
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="deployments",verb="PUT"} 2454
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="clusterroles",verb="WATCH"} 1527
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="replicationcontrollers",verb="WATCHLIST"} 7
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="clusterroles",verb="POST"} 42
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="resourcequotas",verb="LIST"} 304
apiserver_request_latencies_count{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="pods",verb="DELETE"} 913
而apiserver_request_latencies_sum则反映出对各个资源API操作延迟时间的总量
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="replicationcontrollers",verb="LIST"} 554991
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="clusterroles",verb="LIST"} 33586061
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="configmaps",verb="DELETE"} 16466
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="pods",verb="WATCH"} 3430725671235
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="secrets",verb="LIST"} 5843
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="nodes",verb="LIST"} 92849
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="persistentvolumes",verb="LIST"} 9302
apiserver_request_latencies_sum{instance="192.168.2.2:6443",job="kubernetes-apiservers",resource="serviceaccounts",verb="WATCH"} 1378625982766
在Exporter获取的度量指标当中通常会以一下形式表现:
<base_name>_bucket{ label1=value1, label2=value2 }
Summary概要
Summary摘要和Histogram柱状图比较类似,主要用于计算在一定时间窗口范围内度量指标对象的总数以及所有对量指标值的总和。
例如:
apiserver_request_latencies_summary
apiserver_request_latencies_summary_count
apiserver_request_latencies_summary_sum
小结
如第一个项目而言Prometheus Server当前版本在采集数据时并没有使用metrics的数据类型,数据类型更多是Client进行参考,根据不同的场景选择不同的数据类型