> For the complete documentation index, see [llms.txt](https://sb-woms.gitbook.io/sb/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sb-woms.gitbook.io/sb/prometheus/springboot-prometheus-04.md).

# springboot整合prometheus(四)

![](https://timgsa.baidu.com/timg?image\&quality=80\&size=b9999_10000\&sec=1556722981906\&di=4aa1755b5f528609311908f95f79fabf\&imgtype=0\&src=http%3A%2F%2Fwww.maxon.net%2Fuploads%2Fpics%2Fweb_p54.jpg)

prometheus是通过拉取的方式获取数据，prometheus是时序数据库，是用时间为索引，每个label监控项上是一些key-value的数据，数据是累计存储到数据库中的

prometheus拉取springboot上的监控数据的时候，springboot的监控数据是存储在项目内部基于当时时间点的数据，so springboot内部存储的数据只是一个时间点的数据（当时）， 因此不用担心springboot项目会占用太多的内存，监控项是固定的，只是随时间数据在不断的变化，而peometheus会拉取每一个时间的数据，存储在时序数据库中，作分析统计

## 如何区分prometheus中Histogram和Summary类型的metrics？

Histogram和Summary主用用于统计和分析样本的分布情况。

在大多数情况下人们都倾向于使用某些量化指标的平均值，例如CPU的平均使用率、页面的平均响应时间。这种方式的问题很明显，以系统API调用的平均响应时间为例：如果大多数API请求都维持在100ms的响应时间范围内，而个别请求的响应时间需要5s，那么就会导致某些WEB页面的响应时间落到中位数的情况，而这种现象被称为长尾问题。

为了区分是平均的慢还是长尾的慢，最简单的方式就是按照请求延迟的范围进行分组。例如，统计延迟在0\~10ms之间的请求数有多少而10\~20ms之间的请求数又有多少。通过这种方式可以快速分析系统慢的原因。Histogram和Summary都是为了能够解决这样问题的存在，通过Histogram和Summary类型的监控指标，我们可以快速了解监控样本的分布情况。

例如，指标prometheus\_tsdb\_wal\_fsync\_duration\_seconds的指标类型为Summary。 它记录了Prometheus Server中wal\_fsync处理的处理时间，通过访问Prometheus Server的/metrics地址，可以获取到以下监控样本数据：

```
# HELP prometheus_tsdb_wal_fsync_duration_seconds Duration of WAL fsync.
# TYPE prometheus_tsdb_wal_fsync_duration_seconds summary
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.5"} 0.012352463
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.9"} 0.014458005
prometheus_tsdb_wal_fsync_duration_seconds{quantile="0.99"} 0.017316173
prometheus_tsdb_wal_fsync_duration_seconds_sum 2.888716127000002
prometheus_tsdb_wal_fsync_duration_seconds_count 216
```

从上面的样本中可以得知当前Prometheus Server进行wal\_fsync操作的总次数为216次，耗时2.888716127000002s。其中中位数（quantile=0.5）的耗时为0.012352463，9分位数（quantile=0.9）的耗时为0.014458005s。

在Prometheus Server自身返回的样本数据中，我们还能找到类型为Histogram的监控指标prometheus\_tsdb\_compaction\_chunk\_range\_bucket。

```
# HELP prometheus_tsdb_compaction_chunk_range Final time range of chunks on their first compaction
# TYPE prometheus_tsdb_compaction_chunk_range histogram
prometheus_tsdb_compaction_chunk_range_bucket{le="100"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="400"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="1600"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="6400"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="25600"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="102400"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="409600"} 0
prometheus_tsdb_compaction_chunk_range_bucket{le="1.6384e+06"} 260
prometheus_tsdb_compaction_chunk_range_bucket{le="6.5536e+06"} 780
prometheus_tsdb_compaction_chunk_range_bucket{le="2.62144e+07"} 780
prometheus_tsdb_compaction_chunk_range_bucket{le="+Inf"} 780
prometheus_tsdb_compaction_chunk_range_sum 1.1540798e+09
prometheus_tsdb_compaction_chunk_range_count 780
```

与Summary类型的指标相似之处在于Histogram类型的样本同样会反应当前指标的记录的总数(以\_count作为后缀)以及其值的总量（以\_sum作为后缀）。不同在于Histogram指标直接反应了在不同区间内样本的个数，区间通过标签len进行定义。

同时对于Histogram的指标，我们还可以通过`histogram_quantile()`函数计算出其值的分位数。不同在于Histogram通过histogram\_quantile函数是在服务器端计算的分位数。 而Sumamry的分位数则是直接在客户端计算完成。因此对于分位数的计算而言，Summary在通过PromQL进行查询时有更好的性能表现，而Histogram则会消耗更多的资源。反之对于客户端而言Histogram消耗的资源更少。在选择这两种方式时用户应该按照自己的实际场景进行选择。

## 百分位数（quantile）

Prometheus中称为quantile，其实叫percentile更准确。百分位数是指小于某个特定数值的采样点达到一定的百分比。例如，假设0.9-quantile的值为120，意思就是所有的采样值中，小于120的采样值的数量占总体采样值的90%。相应的，假设0.5-quantile的值为x，那么意思就是指小于x的采样值占总体的50%，所以0.5-quantile也指中值（median）。

相对于简单的平均值来说，百分位数更丰富，更能反应出真实的用户体验。常用的百分位数为0.5-quantile，0.9-quantile以及0.99-quantile。这也是Prometheus默认的设置。

> 这只是Prometheus中Summary目前版本的默认设置，在版本v0.10中，这些默认值会废弃，意味着默认的Summary将没有quantile设置。

## bucket

Histogram主要是设置不同的bucket，采用值分别落入不同的bucket。例如上面第一个bucket就是响应时间小于10ms的采样点的数量，第二个bucket就是响应时间小于50ms的采样点的数量，依此类推。

注意后面的采样点是包含前面的采用点的，例如xxx\_bucket的值为30，而xxx\_bucket的值为120，那么意味着这120个采用点中，有30个是小于10ms的，其余90个采样点的响应时间是介于10ms和50ms之间的。 注意+Inf是最高bucket的上限值，所以xxx\_bucket是所有采样点的数量，是Prometheus自动增加的一个bucket。

## 区别

1. histogram有bucket(区间)，summary有quatile(分位数|百分比)
2. summary分位数是客户端(springboot项目)计算上报，histogram中位数是服务端（prometheus server）计算（通过promQL内置函数）

   > 计算quantile值直接用函数histogram\_quantile即可，例如下面是计算0.9-quantile的值， histogram\_quantile(0.9, rate(http\_request\_duration\_milliseconds\_bucket\[10m]))
3. Summary不能对quantile值进行aggregation操作，而Histogram则可以；所以如果针对多实例的场景计算quantile，只能使用Histogram

   > 使用Summary要注意一点，就是不能对Summary产生的quantile值进行aggregation运算（例如sum, avg等）。例如有两个实例同时运行，都对外提供服务，分别统计各自的响应时间。最后分别计算出的0.5-quantile的值为60和80，这时如果简单的求平均(60+80)/2，认为是总体的0.5-quantile值，那么就错了。如果你闭上眼睛，简单思考一下，就会明白对两个quantile值求平均毫无意义。所以如果需要对多个实例的quantile值进行aggregation操作，那么就不能使用Summary。
4. 如果histogram的bucket设置不合理，则最后误差可能会很大；所以如果需要相对精确的结果，而且是单实例场景，那么就使用Summary

   > 使用Histogram计算quantile值，最大的问题就是：因为Histogram采用了线性插值法，所以如果bucket设置不合理，那么最后计算出的值可能偏差比较大。例如在前面的例子中，假设0.9-quantile的结果在10ms\~50ms之间，但是表达式必须返回一个具体的值，这时就采用线性插值法得出36ms。显然这种方法计算出的值可能会有误差，而且范围越大，例如10ms \~ 500ms，那么误差也会越大。 50-10）\*0.9=36ms
5. Summary计算出的quantile值是基于进程开始运行至今的所有采样值计算出来的；而Histogram则是基于最近的一段时间的采样值计算出来的，更符合monitoring系统的本质。

使用Histogram计算quantile值，最大的问题就是：因为Histogram采用了线性插值法，所以如果bucket设置不合理，那么最后计算出的值可能偏差比较大。例如在前面的例子中，假设0.9-quantile的结果在10ms\~50ms之间，但是表达式必须返回一个具体的值，这时就采用线性插值法得出36ms。显然这种方法计算出的值可能会有误差，而且范围越大，例如10ms \~ 500ms，那么误差也会越大。
