Nginx 5xx告警需分场景建模:区分$status与$upstream_status定位根因,结合突增型、绝对量型、实例级聚焦型三类动态阈值,并确保日志格式规范及告警携带完整上下文。

统计 Nginx 5xx 异常并设定合理告警阈值,关键不是“数错了多少”,而是“错得是否影响可用性”。直接看总量或比例容易误判——比如低流量时段 1 个 502 就触发告警,高流量时 50 个 5xx 却被平均稀释掉。应分场景、分来源、分持续时间来建模。
区分 $status 和 $upstream_status,定位故障根因
5xx 错误必须拆开看:Nginx 自己返回的(如 502/503/504),和后端真实返回的(由 $upstream_status 记录)语义完全不同:
- $status == 502 且 $upstream_status == "-" 或空:Nginx 连不上后端(网络中断、端口拒连、upstream 配置错误)
- $upstream_status == "502" 或 "503":后端进程存活但业务异常(DB 拒绝连接、线程池耗尽、代码 panic)
- $upstream_status == "504":后端响应超时,需比对 $upstream_response_time 和 proxy_read_timeout 值是否接近
- $upstream_status == "000":连接失败(无健康节点、DNS 解析失败),属于集群级风险,应优先告警
按场景设定动态阈值,避免一刀切
固定百分比(如“5xx > 1%”)在流量波动大时极易误报。推荐以下三类阈值组合:
- 突增型(秒级敏感):rate(nginx_vts_server_requests_total{code=~"5.."}[2m]) / rate(nginx_vts_server_requests_total[2m]) > 0.005,持续 90 秒 —— 适合捕获雪崩初期
-
绝对量型(低流量兜底):过去 1 分钟内 $upstream_status 匹配
^(50[0-4]|509|000)$的日志行 ≥ 3 条 —— 防止小流量服务失察 - 实例级聚焦型:单个 $upstream_addr 在 60 秒内累计出现 ≥ 5 次 5xx(含 000),立即告警并标注节点 IP —— 支持快速下线故障实例
日志格式与采集必须前置保障
没有正确的日志字段,所有统计都不可靠。务必在 http 块中定义专用 log_format:
并确保 access_log 启用该格式。采集端(Filebeat/Fluentd/nginxlog-exporter)需用正则或 grok 精确提取 upstream_status 字段为数值类型,避免把 “5000ms” 中的 “5” 当作状态码误匹配。
告警要带上下文,不能只甩一个数字
一次有效告警至少应包含:
- 发生时间(精确到秒)、所属 Nginx 实例主机名
- 错误类型(是 502 连接失败?还是 503 后端满载?)
- 影响范围(URI 路径、上游地址 $upstream_addr、请求耗时)
- 最近 5 分钟同 URI 的 5xx 趋势简图(如有 Kibana/ Grafana 集成)
这样运维才能 30 秒内判断:是立刻重启后端,还是调整超时,还是临时切流。


















