可通过Nginx自定义log_format记录$upstream_status,结合实时日志解析(如Telegraf+InfluxDB或nginxlog-exporter)、滚动窗口统计5xx比例,并设置Prometheus告警规则实现回源质量监控。

可以通过 Nginx 的 log_format 自定义日志记录回源状态码,配合日志实时解析与聚合(如用 Go/Python 脚本或 Telegraf + InfluxDB),再通过阈值判断触发告警(如 Slack、企业微信或 Prometheus Alertmanager)。关键在于把上游响应状态码($upstream_http_status 或 $upstream_status)准确打到 access log 中,并确保日志不被缓冲、按行落盘。
1. 在 Nginx 配置中记录上游真实状态码
Nginx 默认 access log 中的 $status 是返回给客户端的状态码,不是回源(即 upstream)的真实响应码。要监控回源质量,必须显式记录 upstream 状态:
- 使用
$upstream_status:记录 Nginx 与 upstream 通信时收到的每个请求的状态码(多个 upstream 时以逗号分隔,如"200,404,502") - 或使用
$upstream_http_status:仅当后端显式设置了Status响应头时才有效,可靠性较低 - 推荐在 http 块中定义专用日志格式,例如:
log_format upstream_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'upstream:"$upstream_addr" '
'upstream_status:"$upstream_status" '
'upstream_response_time:$upstream_response_time '
'request_time:$request_time';然后在 location 或 server 块中启用:access_log /var/log/nginx/upstream.log upstream_log;
2. 实时采集并统计状态码分布
避免轮询大文件或依赖定时脚本扫日志。推荐轻量、低延迟方案:
- 用
tail -n +1 -f流式读取新日志行,配合 awk / Python 按秒/分钟窗口聚合upstream_status字段(注意处理多值,如拆分"200,502") - 更可靠的做法是接入 Telegraf(配置
tailinput 插件 +grokparser),将每条日志解析为指标,写入 InfluxDB 或 Prometheus Remote Write 目标 - 若已用 Prometheus 生态,可用
nginxlog-exporter(支持自定义正则提取upstream_status),暴露为nginx_upstream_status_count{code="502", host="api.example.com"}类型指标
3. 设置动态预警规则
只看单次 502 不够,需关注异常比例和持续性:
- 定义滚动窗口(如最近 2 分钟),计算 5xx 占所有 upstream 请求的比例;超过 5% 持续 3 个周期(6 分钟)即告警
- 对特定 upstream(如
backend-api)单独设阈值,例如 404 突增可能意味着路由配置错误,503 突增可能预示上游过载 - Prometheus 示例 rule:
groups:
- name: upstream-alerts
rules:
- alert: Upstream5xxRateHigh
expr: |
sum(rate(nginx_upstream_status_count{code=~"5.."}[2m]))
/
sum(rate(nginx_upstream_status_count[2m])) > 0.05
for: 6m
labels:
severity: warning
annotations:
summary: "High upstream 5xx rate on {{ $labels.host }}"
4. 补充建议:提升数据准确性
几个容易忽略但影响监控可信度的点:
- 确保
log_subrequest on;(默认 off),否则子请求(如 auth_request、mirror)的 upstream 日志不会记录 - 关闭日志缓冲:
access_log /path/log upstream_log flush=1;,避免告警延迟 - 区分不同 upstream:在 proxy_pass 后加
upstream_name变量(通过 map 模块或 set 指令),让日志和指标带来源标识 - 对重试请求(
proxy_next_upstream触发),$upstream_status会包含全部尝试结果,需按需过滤首跳或末跳状态











