在Grafana中展示Nginx请求延迟P95/P99需用Prometheus的histogram_quantile函数计算直方图分位数,保留upstream、status等标签用于下钻;指标须含le标签且由nginx-prometheus-exporter或OpenResty Lua上报;PromQL需sum by(le, upstream)聚合,窗口选30s;图表应并列P95/P99、叠加upstream耗时与5xx错误率,并辅以Heatmap和日志归因。

直接在 Grafana 中展示 Nginx 请求延迟的 P95 与 P99,核心是用 Prometheus 的 histogram_quantile 函数计算直方图分位数,并保留关键标签(如业务路径、上游服务、状态码)用于下钻分析。平均值毫无意义,P95/P99 才反映真实用户体感。
确保 Nginx 正确上报直方图指标
原生 Nginx 不输出直方图,必须借助 exporter 或 Lua 模块:
- 推荐使用 nginx-prometheus-exporter,启用
--enable-static-stats或解析 access log;它会将$request_time或$upstream_response_time自动转为nginx_http_request_duration_seconds_bucket这类直方图指标 - 若用 OpenResty,可在
log_by_lua_block中调用prometheus:observe()上报带标签的耗时,例如按uri、upstream、status打标 - 关键:指标必须含
le标签(表示“小于等于该桶边界”),且时间序列需带业务维度,比如{upstream="svc-order", status="200"}
Grafana 中写对 PromQL 查询式
P95 和 P99 必须分开画线对比,不能混在一起:
- P95 总请求耗时:
histogram_quantile(0.95, sum(rate(nginx_http_request_duration_seconds_bucket[30s])) by (le, upstream)) - P99 后端处理耗时:
histogram_quantile(0.99, sum(rate(nginx_http_upstream_response_seconds_bucket[30s])) by (le, upstream)) - 窗口选
[30s]而非[1m],兼顾灵敏度与稳定性;避免用[5s]导致噪声过大 - 务必加
sum(...) by (le, ...)—— 漏掉by (le)会导致函数无法聚合,结果为NaN
图表设计要能定位瓶颈
单看一条 P99 曲线不够,必须叠加对照维度:
- 在同一折线图中并列绘制 P95 和 P99,观察两者差值是否持续拉大:差值变宽说明长尾恶化,不是偶发抖动
- 叠加
request_time与upstream_response_time的 P99 曲线:若前者远高于后者,瓶颈在 Nginx 层(SSL、重写、gzip、限流) - 在下方叠加 5xx 错误率曲线(
sum(rate(...{code=~"5.."}[30s])) / sum(rate(...[30s]))),判断“慢是否伴随错” - 用 Heatmap 面板展示毫秒级分布,例如 X 轴为时间、Y 轴为耗时区间(0–100ms、100–500ms、500ms+),颜色深浅表示请求数密度
补充建议:让分位数真正有用
只出数字不解决问题,要支持快速归因:
- 在日志中同时记录
$request_time、$upstream_response_time、$upstream_addr和$upstream_cache_status,便于查具体慢请求对应哪台机器、是否缓存未命中 - 调试阶段可临时加响应头:
add_header X-Req-Time $request_time; add_header X-Upstream-Time $upstream_response_time;,用curl -I快速验证 - 不要只看全局 P99,按
business_tag(如order、pay)或location分组查询,比如histogram_quantile(0.99, ...{business_tag="pay"})











