如何理解Prometheus查询函数及Grafana直方图百分位绘图异常
问题解答
关于累积密度分布的疑问
你对累积密度分布的理解是正确的,CDF在x点的取值就是概率密度函数曲线在x左侧的总面积,代表随机变量取值小于等于x的概率。你对PromQL执行逻辑的理解也没问题:rate计算过去1分钟内每个bucket的请求增量速率,累加所有bucket的速率就能得到总请求速率,单个le对应bucket的速率除以总速率,就是延迟小于等于该le值的请求占比,完全符合CDF的定义。
关于按标签组合计算分位的疑问
histogram_quantile函数会将输入指标中的le标签作为特殊的桶边界标识,剩下的所有非le标签都会作为独立的分组维度,每个分组单独计算一次分位值。比如你没有做sum聚合的时候,原始bucket指标带有code标签,那么最终计算出来的分位结果会为每一组handler+method+code的组合返回独立的分位值。你当前的sum语句按handler, method, le聚合,相当于把code标签的数值合并了,所以最终只会按handler+method分组返回分位结果。
测试场景分位值等于桶上界的原因
你观察到的现象既不是查询语句错误,也不是Grafana绘图逻辑有问题,是Prometheus直方图分位计算的固有特性,和你的测试场景、桶配置有关:
histogram_quantile默认假设每个桶内的请求延迟是均匀分布的,基于线性插值计算分位值- 你测试时只发起固定延迟的请求,所有请求都落在同一个桶里:3秒的请求满足
2 < 3 <=4,全部落在le=4.0的桶中,此时le=2.0的桶请求数为0,计算0.99分位时插值结果就会直接取该桶的上界4秒 - 你设置
Thread.sleep(4000)时,实际请求延迟会叠加接口处理、指标打点的额外耗时,最终延迟超过4秒,就会落到le=8.0的桶中,计算出来的分位值自然接近8秒 - 这种误差在生产环境会大幅降低:生产环境请求延迟是连续分布的,不会全部集中在同一个桶中,插值结果会更接近真实值。如果要降低误差,可以在你关注的延迟区间配置更密的桶,比如在2秒到8秒之间增加3、5、6、7的桶边界,就能显著提升分位计算的精度。
验证方法
你可以直接执行如下PromQL查看各桶的请求速率,就能确认请求实际落在哪个桶中:
sum(rate(http_request_duration_seconds_bucket{method="POST",handler="TestController.testLatencyTime"}[1m])) by (le)
内容的提问来源于stack exchange,提问作者PainIsAMaster
相关产品推荐
相关产品推荐

