目录

 

 

时间序列

Prometheus 是一个时间序列存储系统,时间序列,即:一个时间点拥有一个对应值,例如:(timestamp, value)

生活中很常见的天气预报就是一个单维的时间序列:[(14:00, 27℃), (15:00,28℃), (16:00,26℃)],这种按照时间戳和值存放的序列也被称之为向量(Vector)。

范围向量

Prometheus — 核心概念_Prometheus

再来举另一个例子,如上图所示,假如有一个 http_requests 指标,它的作用是 “统计每个时间段对应的总请求量是多少”,此时它是一个单维矩阵。

而当我们为 http_requests 指标再加上一个维度:hostname,此时这个指标的作用就变成了 “统计每个时间段内各个 hostname 对应的请求量是多少”,此时这个矩阵区域就拥有了多列向量(每一列对应一个 hostname)的时间序列,当给这个时间序列再添加多个标签(key=value)时,这个矩阵就相应会变成一个多维矩阵。

每一组唯一的标签集合对应着一个唯一的向量(Vector),也可叫做一个时间序列(Time Serie),当在某一个时间点来看它时,它是一个瞬时向量(Instant Vector),瞬时向量的时序只有一个时间点以及它对于的一个值,比如:今天 12:05:30 时服务器的 CPU 负载;而在一个时间段来看它时,它是一个范围向量(Range Vector),范围向量对于着一组时序数据,比如:今天 11:00-12:00 时之间的服务器 CPU 负载。

多维度数据模型

Prometheus 使用到多维数据模型,此模型与 Kubernetes 通过 Label 来组织 Object 的方式非常相似。与 “点数据模型” 相反,点数据模型中的每项指标都是唯一的,而每个不同的参数都将对应不同的指标;而使用 Prometheus 的 “多维数据模型”,所有数据都将按时间序列存储为 Key/Value 对:

<metric name>{<label name>=<label value>, …}

# e.g.
http_requests_total{method="POST", endpoint="/api/tracks"}

Prometheus 中存储的数据单元称为时间序列,是由 metric name(指标)和一系列的 labels(key/value)唯一标识的,不同的 label 则代表不同的时间序列。

  • metric name:该名字由 ASCII 字符,数字,下划线,以及冒号组成,且必须满足正则表达式 [a-zA-Z:][a-zA-Z0-9_:]*,应该具有语义,一般用于表示 metric 的功能,例如:httprequests_total,表示 HTTP 请求的总数。

  • labels:使同一个时间序列有了不同维度的识别,即:多维标签。例如:httprequests_total{method=”get”} 表示所有 HTTP 请求中的 GET 请求。当 method=“post” 时,则标识一个新的 metric。标签中的 key 由 ASCII 字符,数字,以及下划线组成,且必须满足正则表达式 [a-zA-Z:][a-zA-Z0-9_:]*

所以,可以通过指标名(metric name)和标签集(label set)来查询符合条件的时间序列:

http_requests{host="host1",service="web",code="200",env="test"}

查询结果会是一个瞬时向量:

http_requests{host="host1",service="web",code="200",env="test"} 10
http_requests{host="host2",service="web",code="200",env="test"} 0
http_requests{host="host3",service="web",code="200",env="test"} 12

而如果给这个条件加上一个时间参数,查询一段时间内的时间序列:

http_requests{host="host1",service="web",code="200",env="test"}[:5m]

结果将会是一个范围向量:

http_requests{host="host1",service="web",code="200",env="test"} 0 4 6 8 10
http_requests{host="host2",service="web",code="200",env="test"} 0 0 0 0 0
http_requests{host="host3",service="web",code="200",env="test"} 0 2 5 9 12
PromQL 聚合运算

拥有了范围向量,我们是否可以针对这些时间序列进行一些聚合运算呢?没错,PromQL 就是这么干的,比如我们要算最近 5 分钟的请求增长速率,就可以拿上面的范围向量加上聚合函数来做运算:

rate(http_requests{host="host1",service="web",code="200",env="test"}[:5m])

比如要求最近 5 分钟请求的增长量,可以用以下的 PromQL:

increase(http_requests{host="host1",service="web",code="200",env="test"}[:5m])

要计算过去 10 分钟内第 90 个百分位数:

histogram_quantile(0.9, rate(employee_age_bucket_bucket[10m]))
样本

在 Prometheus 中,一个 metric name 和一个 label(key/value)组成了一个样本(Sample),是一个真实的被采集到的时间序列记录数据,包括一个 float64 的值和一个毫秒级的时间戳。Prometheus 将采集的样本放到内存中,默认每隔 2 小时将数据压缩成一个 Block(数据块),持久化到硬盘中,样本的数量越多,Prometheus 占用的内存就越高。

因此在实践中,一般不建议用区分度(Cardinality)太高的标签,比如:用户 IP,ID,URL 地址等等,否则结果会造成时间序列数以指数级别增长(Label 数量相乘)。除了控制样本数量和大小合理之外,还可以通过降低 storage.tsdb.min-block-duration 来加快数据落盘时间和增加 scrape interval 的值提高拉取间隔来控制 Prometheus 的占用内存。

instance 和 job

当 Scrape Target 时,Prometheus 会自动给这个 Scrape 的时间序列附加一些 labels 以便更好的分别,例如:instance,job。Prometheus 会把每个指标赋予 job 和 instance labels。对于 Prometheus 而言,Pull 的一个 Endpoint 称之为一个 instance,多个这样的 instances, 则构成了一个 job。

  • instance:一个单独 Scrape Target, 一般对应于一个进程,使用一个 Endpoint(IP:Port)表示。
  • jobs:一组同种类型的 instances(主要用于保证可扩展性和可靠性),例如:api-server job。
job: api-server

    instance 1: 1.2.3.4:5670
    instance 2: 1.2.3.4:5671
    instance 3: 5.6.7.8:5670
    instance 4: 5.6.7.8:5671

Prometheus — 核心概念_Prometheus_02

如上图所示,这三个 metric name 都是一样,但具有不同的 labels:handler 并以此来标识为不同的 metrics。都是属于 Counter 类型的 metric,所以只会向上累加,且 metrics 中都含有 instance 和 job 这两个 label。

对于每个 instance,Prometheus 都会存储以下的时间序列类型:

  • up{job=”[job-name]", instance="instance-id”}:up 值 =1,表示采样点所在服务健康;否则,网络不通, 或者服务挂掉了。metric up 对监控服务健康是非常有用的。
  • scrape_duration_seconds{job=”[job-name]", instance=”[instance-id]"}:尝试获取目前采样点的时间开销。
  • scrape_samples_scraped{job=”[job-name]", instance=”[instance-id]"}:这个采样点目标暴露的样本点数量。

Prometheus — 核心概念_Prometheus_03

Metric(指标)类型

Prometheus 客户端库主要提供四种主要的 metric 类型:

  1. Counter:一种累加的 metric,典型的应用如:请求的个数,结束的任务数,出现的错误数等等。
    例如:查询 http_requests_total{method=”get”, job=”Prometheus”, handler=”query”} 返回 8。10 秒后,再次查询,则返回 14。

  2. Gauge:一种常规的 metric,可以任意加减,典型的应用如:温度,运行的 goroutines 的个数。
    例如:go_goroutines{instance=”172.17.0.2″, job=”Prometheus”} 返回值 147。10 秒后返回 124。

  3. Histogram:柱状图,可以对观察结果采样,分组及统计。典型的应用如:请求持续时间,响应大小。
    例如:查询 http_request_duration_microseconds_sum{job=”Prometheus”, handler=”query”} 时,返回结果如下图所示。
    Prometheus — 核心概念_Prometheus_04

  4. Summary:类似于 Histogram,提供观测值的 count 和 sum 功能,也提供百分位的功能,即可以按百分比划分跟踪结果。典型的应用如:请求持续时间,响应大小。