Prometheus云原生监控:运维与开发实战
上QQ阅读APP看书,第一时间看更新

4.3.4 摘要

与Histogram类型类似,摘要用于表示一段时间内的数据采样的结果(通常是请求持续时间或响应大小等),但它直接存储了分位数(通过客户端计算,然后展示出来),而非通过区间来计算(Histogram的分位数需要通过histogram_quantile(φfloat,b instant-vector)函数计算得到)。因此,对于分位数的计算,Summary在通过PromQL进行查询时有更好的性能表现,而Histogram则会消耗更多的资源。反之,对于客户端而言,Histogram消耗的资源更少。在选择这两种方式时,用户应该根据自己的实际场景选择。

安装并启动Prometheus后,在访问http://localhost:9090/metrics时可以看到Prometheus自带的一些Summary信息,这些信息和Histogram一样在注释中(#HELP和#TYPE)也会显示,如下所示。


# HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 1.1666e-05
go_gc_duration_seconds{quantile="0.25"} 2.6265e-05
go_gc_duration_seconds{quantile="0.5"} 4.8366e-05
go_gc_duration_seconds{quantile="0.75"} 7.8298e-05
go_gc_duration_seconds{quantile="1"} 0.000280123
go_gc_duration_seconds_sum 0.193642882
go_gc_duration_seconds_count 1907

在上述例子中,可以看到基于Go语言编写的Prometheus的gc总次数是1907,耗时0.193642882s,其中中位数(quantile=0.5)计算的耗时为4.8366e-05s,代表1907次中50%的次数是小于4.8366e-05s的。

Summary类型的样本也会提供3种指标,假设指标名称为<basename>。

·样本值的分位数分布情况,命名为<basename>{quantile="<φ>"},属于计数器类型。

·所有样本值的大小总和,命名为<basename>_sum,属于计数器类型。

·样本总数,命名为<basename>_count,属于计数器类型。

知识拓展:Summary和Histogram的异同

1)它们都包含了<basename>_sum和<basename>_count指标。

2)Histogram需要通过<basename>_bucket来计算分位数,而Summary则直接存储了分位数的值。

3)如果需要汇总或者了解要观察的值的范围和分布,建议使用Histogram;如果并不在乎要观察的值的范围和分布,仅需要精确的quantile值,那么建议使用Summary。

Summary的强大之处就是可以利用除法去计算时间的平均值。如果要从Histogram和Summary中计算最近5分钟内的平均请求持续时间http_request_duration_seconds,可以用如下表达式进行。


rate(http_request_duration_seconds_sum[5m])/rate(http_request_duration_seconds_
  count[5m])

count本质上是一个计数器,sum通常情况下也会像计数器那样工作。但是Summary和Histogram可能观察到负值,比如温度(-20℃),这种情况下会导致观察的总量下降,无法再使用rate函数。

比如下面的例子就可以计算过去5分钟内每次响应中返回的平均字节数。


sum without(handler)(rate(http_response_size_bytes_sum[5m])) 
/ 
sum without(handler)(rate(http_response_size_bytes_count[5m]))

关于这个例子,我们需要注意几点。

·因为http_response_size_bytes_count和http_response_size_bytes_sum是计数器类型,所以必须在计算前先使用rate等函数。

·因为Prometheus的API会有很多handler,所以可以使用without过滤掉handler的返回值。

·PromQL要先执行rate()再执行sum(),不能先执行sum()再执行rate()。

·在统计学上,尤其是计算平均值时,要先进行sum等求和运算再做除法。对一个平均值再求平均是不正确的,如下所示。


// 合法
sum without(instance)(
    sum without(handler)(rate(http_response_size_bytes_sum[5m]))
  )
/
sum without(instance)(
    sum without(handler)(rate(http_response_size_bytes_count[5m]))
  )

// 非法
avg without(instance)(
    sum without(handler)(rate(http_response_size_bytes_sum[5m]))
  /
    sum without(handler)(rate(http_response_size_bytes_count[5m]))
)

// 非法
avg(http_request_duration_seconds{quantile="0.95"})

学完这些知识点,再来通过两个关于count的案例夯实一下理论。

案例一:计算所有的实例CPU核心数。


count by (instance) ( count by (instance,cpu) (node_cpu_seconds_total{mode=
  "system"}) )

案例二:计算单个实例192.168.1.1的CPU核心数。


count by (instance) ( count by (instance,cpu) (node_cpu_seconds_total{mode="system",
  instance="192.168.1.1"})