
Nginx 监控这件事很多人一开始想复杂了。Zabbix 要拿到 Nginx 的运行状态并不需要装额外探针也不一定非要解析访问日志最稳定的入口其实是 Nginx 自带的 stub_status 状态页。只要把它打开再用 Zabbix Agent 把里面的几个数字读回来就能完成请求量、并发连接、读写状态的监控再配上触发器和图形连接数异常、请求速率突变这些情况都能直接看到。这篇内容按实际落地顺序来拆先讲 Nginx 状态页每个字段是什么意思再讲怎么让 Zabbix Agent 把数据采回来然后是 Zabbix 前端里的监控项、触发器和图形怎么配最后做一轮实测把请求打起来再去看统计结果怎么解读。适合刚接触 Zabbix 监控 Nginx 的人也适合已经在用 shell 脚本采集、但想转成 Zabbix 规范化监控的人。1. 先搞清楚 nginx 状态页Zabbix 监控 Nginx 的数据从哪来1.1 stub_status 输出字段对照Zabbix 监控 Nginx底层数据源不是日志而是 Nginx 自己维护的计数器。只要在 Nginx 配置里启用 stub_status访问状态页就能看到一小段纯文本Active connections: 291 server accepts handled requests 16630948 16630948 31070465 Reading: 6 Writing: 179 Waiting: 106这段文本虽然短但每个字段都有明确含义。字段含义类型Active connections当前活动连接数瞬时值acceptsNginx 启动以来累计接受的客户端连接总数累计值handled成功处理的连接总数累计值requests累计处理的客户端请求总数累计值Reading正在读取请求头的连接数瞬时值Writing正在读取请求体、处理请求或写响应的连接数瞬时值Waiting空闲的 keep-alive 连接数瞬时值第一行Active connections是当前活动连接数。注意它包含后面 Reading、Writing、Waiting 三类的总和所以只要 Nginx 活着这个数值通常不会是 0。第二行是固定表头server accepts handled requests。第三行的三个数字分别对应表头都是只增不减的累计计数器只有 Nginx 重启才会归零。第四行的 Reading、Writing、Waiting 是三个瞬时值。一个请求从进入到结束通常会依次经过 Reading、Writing 两个阶段最后进入 Waiting或者直接关闭连接。这几个字段之间的换算关系是Active connections Reading Writing Waiting。理解这个关系后面看图形和触发器才不会被数字骗到。1.2 哪些指标值得接进 Zabbix不是每个字段都必须接进来但下面这几个我建议至少都要有。请求速率是最核心的指标对应 requests 计数器看的是单位时间内处理了多少请求也就是平时说的 QPS。只看累计值没有意义必须换算成速率。新建连接速率对应 accepts 计数器看的是单位时间内来了多少新连接。这个值和 QPS 的区别在于keep-alive 生效的情况下一个连接上可以连续发多个请求所以请求速率通常远大于连接速率。当前并发连接数对应 Active connections是最直观的负载指标。但它不能单独说明问题必须结合 Reading、Writing、Waiting 一起看。Reading 如果持续偏高说明有一些客户端请求头发得很慢或者请求头一直没发完。Writing 持续偏高说明 Nginx 正在大量往客户端写响应这时候要关注带宽和上游服务能不能跟上。Waiting 高反而是正常现象说明大量连接是空闲 keep-alive对静态资源或高并发 Web 服务很常见。把这些字段全部接进 Zabbix才算真正把 Nginx 的运行状态看完整。2. 环境准备与最小配置让 Nginx 先吐出状态数据2.1 确认 Nginx 是否支持 stub_statusstub_status 不是所有 Nginx 都默认包含。编译 Nginx 时如果没有加--with-http_stub_status_module这个功能就不存在配置写了也会报错。先检查当前 Nginx 有没有这个模块nginx -V 21 | grep -o http_stub_status_module如果输出里有http_stub_status_module说明支持。如果没有有两个方向重新编译 Nginx 时加上这个模块或者换成已经默认包含该模块的发行版软件包。很多发行版和官方仓库自带的 Nginx 都已经开启了这个模块但自编译版本一定要单独确认。这里提醒一下执行nginx -V时编译参数是在标准错误输出里所以我加了21把错误输出重定向到同一路。很多人第一次只看第一行 version以为不支持其实是没看全。2.2 Nginx 状态页配置示例与安全限制确认模块存在后在 Nginx 的 server 配置里加一个 location。以下是一份最小配置server { listen 80; server_name _; location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all; } }这里最关键的是allow和deny。stub_status 本身没有任何认证机制任何人能访问就能看到你的连接数、请求量和连接状态。如果把状态页暴露到公网内部运行信息等于公开了。所以默认只允许本机访问是最稳妥的做法。如果你的 Zabbix Agent 和 Nginx 不在同一台机器上不要直接把deny all删掉应该改成只允许采集机 IP 访问location /nginx_status { stub_status on; access_log off; allow 192.168.1.100; deny all; }改完配置先检查再重载nginx -t nginx -s reloadnginx -t这一步不能省。stub_status 的 location 如果配置在错误的上下文里或者和已有配置冲突reload 会直接失败。2.3 用 curl 验证状态页是否生效配置完成之后先在 Nginx 所在机器上验证curl -s http://127.0.0.1/nginx_status如果能看到开头那段文本说明状态页已经可以访问了。如果返回 404说明 location 没生效或者配置在了错误的 server 块里。如果返回 403大概率是deny all生效了而你的请求来源 IP 不在allow列表里。这里有个容易忽略的点如果你的 Nginx 不是监听 80 端口或者同时有 HTTPSURL 里要带上实际协议和端口例如http://127.0.0.1:8080/nginx_status。先花一分钟把 curl 这步跑通后面会省很多时间。3. Zabbix Agent 接入一条 UserParameter 和一个监控项的关系3.1 安装与基础配置 Zabbix AgentZabbix Agent 是部署在 Nginx 所在机器上的采集程序。它的作用和 Nginx 状态页互补状态页负责提供数据Agent 负责把数据读出来再交给 Zabbix Server。安装方式要看你的系统和 Zabbix 版本直接使用官方仓库安装 zabbix-agent 即可。装完需要修改配置文件常见要确认三个参数Server192.168.1.10 ServerActive192.168.1.10 Hostnameweb01Server是允许给这台 Agent 下发被动采集请求的 Zabbix Server 地址。ServerActive是主动上报要连接的 Server 地址。Hostname是 Agent 上报时使用的名字在 Zabbix 前端添加主机时要保持一致特别是主动检查时Hostname 对不上会直接导致数据丢失。这里解释一下被动检查和主动检查的区别。被动检查是 Zabbix Server 主动连接 Agent 的 10050 端口要数据主动检查是 Agent 主动连接 Server 的 10051 端口上报数据。自定义 UserParameter 两种方式都支持但排查问题时的思路不一样后面会详细说。改完配置启动服务systemctl restart zabbix-agent systemctl status zabbix-agent3.2 通过 UserParameter 把 nginx_status 转成监控项Zabbix Agent 默认不认识 nginx 的 key需要通过 UserParameter 来定义。UserParameter 的格式很简单一个 key一个命令Agent 执行命令把标准输出作为监控值返回。在/etc/zabbix/zabbix_agentd.d/目录下创建一个 nginx.conf写入以下内容UserParameternginx.active,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk /Active connections/{print $3} UserParameternginx.accepts,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk NR3{print $1} UserParameternginx.handled,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk NR3{print $2} UserParameternginx.requests,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk NR3{print $3} UserParameternginx.reading,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk /Reading/{print $2} UserParameternginx.writing,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk /Writing/{print $4} UserParameternginx.waiting,/usr/bin/curl -s --max-time 3 http://127.0.0.1/nginx_status | awk /Waiting/{print $6}逐个拆一下。每行都是一个 key例如nginx.active。后面的命令先用 curl 抓取状态页再用 awk 提取对应字段。awk 的写法要特别注意。第三行的 accepts、handled、requests 是三个连续数字所以分别用NR3定位到第三行再打印第 1、2、3 列。Reading、Writing、Waiting 在同一行里所以要先用正则匹配到这一行再打印对应列。Writing 是第 4 列Waiting 是第 6 列这个顺序很多人会弄错。命令里的--max-time 3不是随便加的。如果状态页异常导致 curl 一直挂住Agent 执行这个 UserParameter 就会卡住严重时会占满 Agent 的检查线程影响这台机器上的其他监控项。加上超时时间最坏 3 秒也会退出。改完配置后重启 Agentsystemctl restart zabbix-agent3.3 先用 zabbix_get 还是前端测试功能配置完 UserParameter不要急着去 Zabbix 前端创建主机先在命令行验证一遍 key 能不能查到值。在有 zabbix-get 工具的机器上执行它通常在 Zabbix Server 或 Proxy 上zabbix_get -s 192.168.1.20 -k nginx.requests返回一个数字说明这条链路通了。如果提示 Not supported 或者没有输出先不要怀疑 Zabbix 配置回到 Nginx 机器上直接执行那条 UserParameter 命令看有没有结果。这里有个容易踩的坑你手动执行命令时用的是 root 用户而 Zabbix Agent 运行时的用户通常是 zabbix两个用户的环境变量、权限、可执行路径可能都不一样。比如 zabbix 用户没有权限访问某个目录或者 SELinux 拦截了 zabbix 用户执行 curl都会导致手动执行正常、Agent 执行失败。新版 Zabbix 前端在监控项配置里也有一个 Test 按钮可以直接测试当前主机上的 key返回结果和报错更直观。实际排查时我一般按三个地方顺序看Agent 所在机器手动执行命令、zabbix_get 从 Server 端测试、前端 Test 按钮看报错。4. 创建主机、监控项、触发器数据到告警的完整链路4.1 在 Zabbix 前端添加主机与监控项命令行验证通过后进入 Zabbix Web 界面按照 配置 → 主机 → 创建主机 的路径添加一台主机。填写主机名时要注意Agent 配置文件里的 Hostname 和这里的主机名必须一致否则主动检查会失败。接口配置里选择 Agent填写 Nginx 所在机器的 IP 和默认端口 10050。添加监控项有两条路线。一条是直接链接模板Zabbix 模板库里有 Nginx by HTTP、Nginx by Zabbix agent 2 这类现成模板不同版本的模板数量和名称会有差异底层采集方式也是去读状态页适合不想自己维护 key 的人。另一条是手动创建监控项用刚才定义的 UserParameter 键值自由度更高也更容易理解每个数字怎么来的。如果你是第一次做我更建议先手动创建。原因很简单自动模板会隐藏很多细节一旦出了问题你很难判断是状态页的问题、Agent 的问题还是模板映射的问题。手动创建一遍等于把链路里的每个环节都摸清楚了。手动创建监控项时以nginx.requests为例名称Nginx Requests类型Zabbix Agent键值nginx.requests信息类型数字无正负更新间隔1m 或 30s 都可以历史数据保留7d趋势数据保留365d其他几个 key 按同样方法创建。4.2 请求速率、连接数怎么存储和计算单位这里要解决一个关键问题accepts、handled、requests 这三个字段是累计值直接存进 Zabbix 只能看到一根一直向上的线很难判断当前请求量到底是多少。所以必须让 Zabbix 把累计值换算成速率。在 Zabbix 监控项配置里有一个字段叫“存储值”可以选“原样存储”“增量简单变化”和“增量每秒速率”。存储方式适用场景示例原样存储瞬时值当前是多少就存多少active、reading、writing、waiting增量简单变化累计值的两次差值accepts 每次变化量增量每秒速率累计值换算成每秒速率requests、accepts、handled对 requests、accepts、handled 这三个累计计数器应该选择“增量每秒速率”单位写成 req/s 或 conn/s。这样 Zabbix 会在后台自动计算两次采集之间的差值再除以时间间隔得到每秒速率。如果你不想在监控项里改存储方式也可以用预处理步骤里的“每秒更改量”来实现同样效果。两者本质上是一样的看你习惯哪种。唯一要注意的是如果 Nginx 在两次采集之间重启过计数器归零速率可能会出现一次很大的负值或异常值统计图形上会出现明显的断点这是正常现象不是系统崩溃。active、reading、writing、waiting 这四个瞬时值就保持“原样存储”它们的数值本身就是当前状态不需要做速率换算。4.3 触发器和告警阈值怎么定监控项建好后数据会不断进入 Zabbix但没人盯着图形的话异常还是发现不了。触发器的意义就是自动判断数值是否超过预期。触发器配置路径是 配置 → 主机 → 触发器 → 创建触发器。以活跃连接数为例一个简单表达式last(/web01/nginx.active)10000含义是当前活跃连接数大于 10000 时触发警告。再比如请求速率min(/web01/nginx.requests,5m)5000含义是最近 5 分钟请求速率平均值超过 5000 req/s 时触发。阈值定多少没有标准答案取决于你的业务。我建议先让 Zabbix 跑两三天积累一段基线数据再根据图形里的峰值来定警告和严重阈值不要凭感觉拍脑袋。第一次设置可以把阈值放宽一点确认告警链路能正常触发后再往回收。触发器还可以设置恢复表达式也就是数值降到多少以下时自动恢复为正常。这个最好一起配好否则每次数值震荡都会反复触发、恢复告警会很吵。要测试告警链路的完整效果除了触发器还需要配置好动作和通知方式。如果暂时没配邮件或其他通知也可以先只做触发器通过 Zabbix 首页的告警记录来确认触发是否成功。5. 实测一轮用请求压一压再去看统计结果和图形5.1 制造流量curl 循环或 ab 简单压测配置完成之后最关键的一步就是实测。没有流量监控图形是一条平线你很难判断数据到底有没有采集成功。最简单的测试方法是用 curl 发一批请求。在 Nginx 机器上执行for i in $(seq 1 1000); do curl -s -o /dev/null http://127.0.0.1/; done这个循环会向本机 Nginx 发送 1000 次请求每次丢弃响应内容。优点是环境干净不需要额外工具。缺点是速度不够快产生的请求速率不会特别高。如果你机器上有 ab也就是 ApacheBench可以压得更明显一些ab -n 5000 -c 100 -k http://127.0.0.1/这条命令的含义是总共发送 5000 个请求同时保持 100 个并发连接-k表示启用 keep-alive。ab 在测试时会持续请求能把 Nginx 的请求速率和活跃连接数明显拉起来。执行的时候建议一次只跑一种跑完等一分钟让 Zabbix 完成几个采集周期再去前端看数据。如果立刻去看采集周期还没到可能什么都看不到。5.2 分析 Latest data 和 Graphs进入 Zabbix 前端的“监测 → 最新数据”选择刚才创建的主机就能看到每条监控项的当前值。这时候你看到的应该是有具体数字的绿色状态而不是“不支持”或“无数据”。以刚才 ab 压测为例压测过程中可以看到 requests 数值冲上去压测结束后又会回落。如果配上图形把请求速率、活跃连接、Reading、Writing、Waiting 放在同一张图里观察能很直观地看到整个请求生命周期的变化。如果你没有在监控项里单独创建图形也可以在仪表盘中添加一个图表组件数据源选择对应主机的监控项。Zabbix 的图表组件支持把多个监控项叠加到同一张图上非常适合对比 Active connections、Reading、Writing、Waiting 这几个相关指标。5.3 从数据反向判断 Nginx 状态是否健康数据有了接下来的重点是怎么读这些数字。先看 active connections 和 waiting 的关系。如果活跃连接数很高但 waiting 也很高说明大量连接是空闲 keep-aliveNginx 实际压力不大只是在维持长连接。如果活跃连接数高waiting 却很低说明连接都在真正干活这时候负载才是真的高。再看 accepts 和 handled 的对比。正常情况下这两个数值应该非常接近。如果 handled 长期明显小于 accepts说明有一部分连接没有被 Nginx 成功处理可能原因是 worker_connections 配置过低连接数被系统层面拒绝了。通过 Zabbix 监控这两个值的曲线差值能比看错误日志更早发现问题。再看请求速率和连接速率的关系。用 requests 速率除以 accepts 速率可以得到平均每个连接上的请求数。如果这个值接近 1说明 keep-alive 基本没起作用客户端每次请求都新建连接连接效率很低。如果明显大于 1说明 keep-alive 生效良好一个连接上处理了多个请求。Reading 和 Writing 是更细的观察点。静态资源站点在压测时Writing 会明显升高因为 Nginx 正在往客户端输出响应。如果 Writing 持续高位但 requests 并不高可能是网络带宽打满了响应写不出去。Reading 持续高位则要小心可能是客户端请求头发送缓慢也可能是存在慢连接这种情况即使活跃连接数不高worker 也可能被拖住。这些判断不能只看一两个采样点最好结合 5 分钟、1 小时的时间窗口来看趋势。这也是为什么前面建议把趋势数据保留时间设长一些。6. 常见问题排查与生产环境落地的边界6.1 Agent 显示 Not supported 时按什么顺序查Zabbix Agent 返回 Not supported 是监控 Nginx 时最常遇到的问题。很多人第一反应是去改 Zabbix 配置其实大多数时候问题出在 Agent 侧。我的排查顺序是固定的。第一步直接手动执行那条 UserParameter 命令看有没有输出。如果命令本身就没输出说明状态页、curl、awk 里有一环断了。第二步确认执行用户。Zabbix Agent 通常以 zabbix 用户运行手动用 root 执行成功不代表 zabbix 用户能执行。可以用su - zabbix -s /bin/bash -c 命令来模拟 Agent 的执行环境。第三步看 Agent 日志默认在 /var/log/zabbix/zabbix_agentd.log。日志里会记录 key 对应的错误信息比如命令找不到、执行超时、权限不足等。第四步改完 UserParameter 后确认重启了 Agent。UserParameter 是在 Agent 启动时读取的不重启不会生效。第五步从 Server 端用 zabbix_get 测试连通性。这一步能区分问题是出在 Agent 执行命令还是 Server 与 Agent 之间的网络、端口、密钥配置上。还有一个常见问题Linux 有 SELinux 或 AppArmor 环境时zabbix 用户执行 curl 连接本机端口可能会被拦截。手动执行正常Agent 执行就是失败排查到这一步时要看安全审计日志确认是不是被策略拦截了。6.2 状态页不能直接暴露在公网前面配置 Nginx 状态页时写了 allow 和 deny这个限制在正式环境同样重要。stub_status 只有数据输出没有认证、没有访问控制任何人拿到状态页地址就能看到你所有虚拟主机的连接数、请求量等信息。这些数据单独看不算机密但结合业务时序可能暴露促销活动、低谷期等运营信息。所以生产环境要遵守几个原则状态页只监听内网地址或只允许内网访问。Zabbix Agent 与 Nginx 部署在一起时直接限制为 127.0.0.1。如果需要远程采集优先让 Agent 本机读取不要让其他机器直接 HTTP 访问状态页。Nginx 服务本身就开启了公网监听时更要检查 allow 列表不要把公网网段放进去。另外状态页建议使用独立 location不要放在一个会匹配大量路径的通用规则里避免被扫描工具顺带发现。access_log off也要保留否则每个状态页请求都会写一条访问日志白白增加磁盘 IO。6.3 多实例和规范化模板、宏、命名规则如果只有一台机器手动创建监控项没什么问题。一旦机器多起来比如七八台 Nginx 都要监控逐台手动创建就很痛苦而且容易漏配。这时候应该把监控项、触发器、图形整理成模板。在模板里创建好 nginx.active、nginx.requests 这些监控项和对应的触发器再把模板链接到主机上所有主机自动继承配置。后续要加阈值、加图形只需要改模板一处所有主机同步生效。模板里的阈值可以做成宏比如{$NGINX_ACTIVE_WARN}、{$NGINX_REQ_HIGH}。这样在不同业务机器上可以差异化覆盖不用复制整个模板。比如 A 机器请求量本来就大警告阈值定 8000B 机器是小业务阈值定 1000。用宏就能在同一套模板下按主机单独调整。key 的命名也要规范。前面用的 nginx.active、nginx.requests 就是比较清晰的命名方式。如果一台机器上有多个 Nginx 实例建议在 key 里带实例编号比如 nginx1.active、nginx2.active避免数据串台。6.4 历史数据保留和监控频率最后聊一下采集频率和数据保留。对 Nginx 监控来说30 秒到 1 分钟的采集间隔已经足够。不要看到别人用 1 秒间隔就觉得越快越好越短的间隔意味着越多的 Agent 执行、越多的 Server 轮询和越大的存储开销。尤其是自定义 UserParameter 每次都执行 curl 命令如果一台机器上有 7 个 nginx key每个采集周期就有 7 次 curl。机器数量一多这个开销会被明显放大。如果想降低开销有两个方向。一个方向是把采集间隔统一调大成 1 分钟。Nginx 的指标本来就是慢变量1 分钟内的尖峰对告警影响不大。另一个方向是写一个单独的采集脚本一次抓取状态页把结果写到临时文件再由多个 UserParameter 去读文件避免每次都重新 curl。后一种方案适合机器多、又不愿意放宽采集间隔的场景但脚本逻辑和错误处理要写得更严谨否则一个脚本崩了所有 nginx key 都会失效。历史数据保留方面原始监控值保留 7 到 14 天足够趋势数据保留 365 天用于回顾容量。如果你发现自己经常要回溯更久之前的 Nginx 指标建议单独导出到外部存储不要无限拉长 Zabbix 的保留周期否则数据库膨胀之后整个监控系统的查询速度都会受影响。我个人更建议按这个顺序落地先把状态页和 curl 验证跑通再用 zabbix_get 确认 key 有数据然后创建主机和监控项最后才是触发器和图形。看起来流程更长但每一步都有明确的成功标准出了问题也知道在哪一段排查。真正跑过一轮测试之后你会发现 Zabbix 监控 Nginx 并不复杂难点反而不是工具而是你愿不愿意把一个累计计数器、一个状态页字段吃透。