多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

第5篇 Nginx 监控:流量、连接与性能指标

第5篇 Nginx 监控:流量、连接与性能指标 Nginx 在现代架构中往往扮演着双重角色——它既是承载静态资源的 Web 服务器也是转发动态请求的反向代理服务器。这种双重身份意味着任何一次性能波动都可能来自两个截然不同的层面静态文件读取受阻抑或是上游服务响应迟滞。正因如此监控 Nginx 从来不是简单地看一眼 QPS 曲线。我们需要回答三个问题流量是否健康——请求速率、状态码分布、带宽消耗是否在预期区间内连接是否可控——活跃连接数、等待连接、长连接复用率是否逼近瓶颈性能是否达标——请求处理延迟、上游响应时间、缓存命中率是否出现了劣化趋势。本文将以 nginx 1.31 与 nginx-prometheus-exporter 1.5.0 为基础环境先厘清 Nginx 的指标体系与采集链路再逐一拆解流量、连接与性能三条监控主线最终给出可落地的告警规则与可视化方案。目标是让你在故障发生之前就从数据中读出征兆。本文环境nginx 1.31官方 Docker 镜像nginx-prometheus-exporter 1.5.0prom/prometheus:v3本篇只讲开源版 nginx。--nginx.plus模式下的nginx_plus_*指标upstream 耗时、缓存命中、状态码分布不在讨论范围内。一、验证环境搭建Prometheus 的文本协议只认metric_name{labelvalue} 数值这一种形态。stub_status 输出的是给人看的对齐文本两者格式不兼容因此中间需要搭建翻译层 nginx-prometheus-exporter。1、搭建 Nginx 并开启 stub_status1开启 stub_statusserver { listen 8011; server_name localhost; location /nginx_status { stub_status on; access_log off; # allow 127.0.0.1; # deny all; } }2启动 Nginxdocker run -d --name nginx \ --restartno \ --network my-bridge \ -p 80:80 \ -p 8011:8011 \ -e TZAsia/Shanghai \ -v /data/volumes/nginx/nginx.conf:/etc/nginx/nginx.conf \ -v /data/volumes/nginx/conf.d:/etc/nginx/conf.d \ nginx:1.313验证/nginx_status地址返回示例$ curl localhost:8011/nginx_status Active connections: 2 server accepts handled requests 2 2 3 Reading: 0 Writing: 1 Waiting: 1stub_status 一共就 7 个数字全是/proc级别的累计计数器和瞬时值。它是 nginx 监控唯一的零成本数据源但边界也很明确——状态码、upstream、耗时一个都没有。stub_status 字段含义对应 Prometheus 指标类型Active connections当前已建立的全部连接数nginx_connections_activeGaugeaccepts累计接受的连接数nginx_connections_acceptedCounter无_total后缀handled累计成功处理的连接数nginx_connections_handledCounter无_total后缀requests累计客户端请求数是请求不是连接nginx_http_requests_totalCounterReading正在读取请求头的连接数nginx_connections_readingGaugeWriting正在向客户端写响应的连接数nginx_connections_writingGaugeWaiting空闲的 keepalive 连接数nginx_connections_waitingGauge三条恒等关系Active Reading Writing Waiting任何时候都成立对不上说明抓取瞬间前后不一致。accepts - handled累计被丢弃的连接数。nginx 的listen队列满了才会出现。requests / handled平均每个连接跑了几个请求。这个比值是 keepalive 有没有生效的直接证据。2、搭建 nginx-prometheus-exporterdocker run -d --name nginx-exporter \ --rm \ --restart no \ --network my-bridge \ -p 9113:9113 \ -e TZAsia/Shanghai \ nginx/nginx-prometheus-exporter:1.5.0 \ --nginx.scrape-urihttp://nginx:8011/nginx_statusWeb 服务相关Exporter 自身服务参数默认值说明--web.listen-address:9113Exporter 监听地址端口可多组--web.listen-address0.0.0.0:9113--web.telemetry-path/metricsprometheus 拉取指标路径--web.config.fileweb 配置文件配置 TLS、basicAuth 认证exporter‑toolkit 格式--[no‑]web.systemd‑socketfalse使用 systemd socket 监听LinuxNginx 采集核心参数参数默认值说明--nginx.scrape‑urihttp://127.0.0.1:8080/stub_statusNginx 状态接口地址开源Nginxhttp://ip/stub_statusPlushttp://ip/apiunix socketunix:/var/run/nginx.sock:/stub_status--[no‑]nginx.plusfalse启用 Nginx‑Plus 模式读取 api 接口普通 Nginx 务必加--no‑nginx.plus--nginx.timeout5s请求 nginx status 接口超时时间3、接入 prometheus- targets: - 10.0.2.15:9113 labels: svc: nginx type: nginx nginx_port: 80验证$ docker exec -it prometheus promtool check config /etc/prometheus/prometheus.yml Checking /etc/prometheus/prometheus.yml SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax打开 Prometheus 的Status → Targetssvcnginx显示UP就完成了。二、核心指标解析OSS 版 nginx 原生指标只有 8 个加上 exporter 自带的运行时指标一共四类。#分类指标前缀监控内容1可用性nginx_up、nginx_exporter_build_infostub_status 是否抓得到、exporter 版本2连接nginx_connections_*活跃/读取/写入/等待连接、累计接受与处理3流量nginx_http_requests_total累计客户端请求数唯一能算 QPS 的指标4exporter 自身process_*、go_*、promhttp_*是 exporter 进程的不是 nginx 的5nginx 进程资源原生无需node_exporter或 cAdvisor 补nginx 自身 CPU、内存、文件描述符1、可用性主要指标Prometheus 指标名类型含义说明nginx_upGauge上次抓取 stub_status 是否成功。1成功0失败。这是最该配的第一条告警nginx_exporter_build_infoGauge恒为 1版本信息在标签里version、revision、goversionnginx_up为 0 的含义比想象中宽nginx 挂了是一种stub_status 返回 403 是另一种DNS 解析失败、连接超时、TLS 握手失败也都算。它只能告诉你这一环断了具体断在哪要配合up{jobnginx}一起看up 0Prometheus 到 exporter 之间的问题。up 1且nginx_up 0exporter 到 nginx 之间的问题。nginx_exporter_build_info指标示例# HELP nginx_exporter_build_info A metric with a constant 1 value labeled by version, revision, branch, goversion from which nginx_exporter was built, and the goos and goarch for the build. # TYPE nginx_exporter_build_info gauge nginx_exporter_build_info{branchHEAD,goarchamd64,gooslinux,goversiongo1.25.1,revisionb14979c9f3634dcd5a2b158874e713beb3aca3d7,tagsunknown,version1.5.0} 1常用 PromQL# 查看 Nginx 状态 nginx_up{jobcim}2、连接主要指标Prometheus 指标名类型含义说明nginx_connections_activeGauge当前已建立的全部连接数恒等于 reading writing waitingnginx_connections_readingGauge正在读取请求头的连接数反映请求进入的速度nginx_connections_writingGauge正在向客户端写响应的连接数持续偏高说明响应慢、连接被占住nginx_connections_waitingGauge空闲的 keepalive 长连接数不消耗 CPU偏高属正常现象nginx_connections_acceptedCounter无_total后缀累计接受的连接数计算速率必须用rate()不能直接画原始值nginx_connections_handledCounter无_total后缀累计成功处理的连接数与 accepted 之差是被丢弃的连接常用 PromQL# 当前活跃连接数 nginx_connections_active # 现有连接构成三条曲线相加应等于 active nginx_connections_reading nginx_connections_writing nginx_connections_waiting # 连接水位与理论上限的比值 nginx_connections_active / (count(count by (instance) (nginx_connections_active)) * 512) # 512 为 worker_connections 默认值按实际改 # 每秒新建连接数 rate(nginx_connections_accepted[5m]) # 每秒被丢弃的连接数 0 就要看 listen backlog rate(nginx_connections_accepted[5m]) - rate(nginx_connections_handled[5m]) # 平均每连接请求数keepalive 生效程度正常情况下 1 rate(nginx_http_requests_total[5m]) / rate(nginx_connections_accepted[5m]) # 正在写响应的连接占比偏高说明响应慢连接被占住 nginx_connections_writing / nginx_connections_active分析要点active高不等于有问题active高且writing占比高才是问题。前者说明连接多后者说明连接被慢响应占住了。waiting高是正常的。keepalive 空闲连接本来就应该停在 waiting 状态它不用 CPU。看到 waiting 涨就告警是新手最常见的误判。accepts - handled增速大于 0说明有连接在下沉。这个值不会回落只能看增速。连接数上限的账要算两遍worker_processes × worker_connections是理论值nginx 默认worker_connections 512。但 nginx 做反向代理时一个客户端连接会同时占掉两个槽位客户端侧一个、upstream 侧一个。所以真正能承载的客户端连接数大约只有理论值的一半。60 个活跃连接配 512 的上限看着很空如果worker_processes是 2、又在代理 5 个后端实际余量远比数字上看起来小。3、流量主要指标Prometheus 指标名类型含义说明nginx_http_requests_totalCounter累计客户端请求数OSS 版 nginx 唯一能算 QPS 的指标按请求计不按连接计一个 keepalive 连接跑 100 个请求会累加 100nginx_http_requests_total是 OSS 版 nginx 唯一的原生流量指标。常用 PromQL# 总 QPS sum(rate(nginx_http_requests_total[5m])) by (job,instance) # QPS 环比波动识别流量异动 sum(rate(nginx_http_requests_total[5m])) / sum(rate(nginx_http_requests_total[5m] offset 1h)) - 1分析要点抓取间隔 15s、rate窗口 5m是分辨率和平滑度比较平衡的一组值。窗口用 1m 会抖用 15m 会盖掉 5 分钟以内的流量尖峰。QPS 本身没有绝对阈值它取决于容量规划。有意义的判断是环比和同比波动。nginx_http_requests_total是 Counternginx 重启会归零。rate()会自动处理重置但 Grafana 里如果直接画原始值会出现一个向下的尖峰别当成异常。4、exporter 自身exporter 自身指标无实际意义不扩展介绍。5、nginx 进程资源/metrics里的process_*描述的是exporter 进程不是 nginx。nginx 自身工作进程已经拆成多个 worker用 exporter 的process_*去告警 nginx 的 CPU 和内存结论一定是错的。要拿 nginx 真实的进程资源有两条路方案关键指标优点缺点适用场景node_exporter 进程采集器namedprocess_namegroup_cpu_seconds_total、namedprocess_namegroup_memory_bytes、namedprocess_namegroup_open_filedesc、namedprocess_namegroup_num_procs无侵入、按进程名聚合、能拿到 worker 总资源指标量大--collector.processes默认关闭需显式打开物理机 / 虚拟机裸部署cAdvisor容器指标container_cpu_usage_seconds_total、container_memory_working_set_bytes直接对应 cgroup、容器场景天然可用只对容器有效Docker / K8s 部署实际场景中几乎不会使用且默认的/metrics里也没有以上指标因此此处也不扩展介绍。三、告警规则参考#分类告警名称 (alert)级别for触发条件 / 阈值说明1可用性NginxExporterDowncritical1mup{jobnginx} 0Prometheus 到 exporter 链路断2可用性NginxStubStatusUnavailablecritical1mnginx_up 0exporter 到 nginx 链路断多见于 4033连接NginxActiveConnectionsHighwarning5mactive / 上限 70%连接水位预警建议值4连接NginxActiveConnectionsCriticalcritical5mactive / 上限 90%接近上限新连接开始排队5连接NginxConnectionDroppedwarning5m丢弃速率 0.5/saccepts - handled增速转正listen backlog 溢出6连接NginxWritingRatioHighwarning5mwriting/active 0.5且active 50写响应连接占比过高响应变慢7连接NginxKeepaliveIneffectiveinfo15mrequests/accepted 1.2keepalive 未生效连接复用率低建议值 1.28流量NginxQpsAnomalywarning10mQPS 环比波动 50% 且 QPS 10流量暴涨或暴跌建议值四、小结本文围绕 Nginx 监控梳理了三条主线流量、连接与性能。流量层面QPS、带宽与状态码分布反映请求的规模与质量连接层面活跃连接数、等待队列与握手开销揭示服务端的承压状态性能层面响应延迟、上游耗时与缓存命中率则刻画请求处理的效率边界。三者相互关联单独观察任一维度都难以定位问题全貌——流量陡增未必是故障但若伴随连接堆积与延迟抬升则往往指向真实的容量瓶颈。监控体系的有效性不取决于采集指标的数量而取决于是否形成“采集—展示—告警”的闭环采集保证数据可追溯展示保证异常可感知告警保证响应可执行。任一环节缺位监控便退化为事后翻查的日志工具。实践中建议遵循三条原则指标精简优先于大而全告警阈值需结合业务基线动态校准避免静态阈值引发的告警疲劳同时将监控项与容量规划、故障复盘联动让数据真正参与决策而非停留在仪表盘之上。
返回列表