在排查Nginx性能问题时,不少同学习惯直接查看nginx_status或者访问日志,但连接数和请求量只能反映应用层压力。比如一台Nginx主机连接数很低,却出现响应变慢,很可能是CPU软中断处理网卡队列时被打满,或者磁盘IO等待升高导致日志写入变慢。这些操作系统层面的指标不会出现在Nginx的状态页里,只能借助专门的主机监控采集器获取。

node_exporter就是Prometheus生态中负责暴露主机系统指标的组件。它以守护进程方式运行在Nginx所在的Linux服务器上,通过HTTP接口对外提供/metrics数据。Prometheus定期拉取这些数据,就可以获得CPU使用率、内存剩余量、磁盘空间、网络吞吐、文件系统读写延迟等关键信息。结合Nginx自身的stub_status模块,就能同时看到应用层连接状态与系统资源消耗,定位问题时不再靠猜测。
部署node_exporter与Prometheus抓取
node_exporter不需要复杂依赖,官方提供编译好的二进制文件。以Linux x86_64平台为例,下载并解压后放到/usr/local/bin目录即可。建议创建独立系统用户运行,避免使用root权限。
# 下载node_exporter二进制包(替换版本号) wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz tar -zxvf node_exporter-1.8.2.linux-amd64.tar.gz sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/ sudo useradd -rs /bin/false node_exporter
创建systemd服务文件/etc/systemd/system/node_exporter.service,内容如下。注意ExecStart后要写完整路径,--web.listen-address可以自定义监听端口,默认9100。如果服务器有多张网卡,建议绑定内网IP,避免暴露到公网。
[Unit] Description=Node Exporter After=network.target [Service] User=node_exporter Group=node_exporter Type=simple ExecStart=/usr/local/bin/node_exporter --web.listen-address=:9100 [Install] WantedBy=multi-user.target
执行systemctl daemon-reload、systemctl start node_exporter、systemctl enable node_exporter后,通过curl http://127.0.0.1:9100/metrics就能看到大量指标。接着在Prometheus配置文件中添加一个job,让Prometheus定期抓取Nginx主机上的node_exporter。示例配置如下,targets替换为实际IP地址。
scrape_configs:
- job_name: 'node_exporter'
static_configs:
- targets: ['192.168.10.10:9100']
labels:
service: 'nginx-host'
抓取间隔可以根据服务器规模调整,通常15秒到30秒即可。如果Nginx主机数量较多,建议配合Prometheus的文件服务发现或Consul自动发现,避免手动维护targets列表。
开启Nginx状态页与关键指标解读
Nginx默认不开启状态页,需要在配置文件中增加一个location块。通常做法是单独监听一个内网端口或者限制访问来源IP,防止状态数据暴露。下面的配置在Nginx中启用stub_status模块,只允许Prometheus服务器访问。
server {
listen 8080;
server_name 127.0.0.1;
allow 192.168.10.20;
deny all;
location /nginx_status {
stub_status;
access_log off;
}
}
保存后执行nginx -t并reload,访问http://127.0.0.1:8080/nginx_status可以看到类似Active connections: 12、server accepts handled requests等内容。其中Active connections表示当前活跃连接数,accepts是累计接受连接数,handled是累计处理连接数,requests是累计请求数。Reading、Writing、Waiting三个值分别表示正在读取请求头、正在写响应、以及keep-alive等待的连接数。
再看node_exporter提供的系统指标。CPU使用率可以从node_cpu_seconds_total计算得出,这个计数器按CPU核心和模式(user、system、idle、iowait等)分别累加时间。用rate(node_cpu_seconds_total{mode="idle"}[5m])可以得到idle占比,再用1减去idle比例就是整体CPU使用率。内存方面,node_memory_MemAvailable_bytes表示不考虑缓存回收时的可用内存,比传统的MemFree更接近真实可用量。磁盘空间用node_filesystem_avail_bytes结合node_filesystem_size_bytes计算使用百分比。磁盘IO等待则需要关注node_disk_io_time_seconds_total,该指标累计磁盘繁忙时间,配合rate()可以看出磁盘是否成为瓶颈。
网络指标同样关键。node_network_receive_bytes_total和node_network_transmit_bytes_total分别记录网卡累计接收和发送字节数。Nginx作为反向代理时,如果网络吞吐突然打满网卡带宽,即使CPU和内存空闲,请求也会排队超时。因此查看系统指标时要同时关注CPU、内存、磁盘IO和网络四个维度,而不是单独看某一项。
联合指标定位问题与告警规则
把Nginx状态页指标和node_exporter指标放在同一个Grafana仪表盘中,可以快速判断故障类型。例如Nginx的Active connections突然飙升,同时node_network_receive_bytes_total的速率接近网卡上限,说明可能是流量突增或遭受攻击。如果Active connections不高,但CPU的iowait占比持续超过20%,则需要检查磁盘IO,比如日志盘是否性能不足、是否开启了Nginx错误日志的同步写入。
另一种典型场景是内存泄漏。Nginx自己的worker进程通常内存占用稳定,但如果主机上还有其他服务,或者Nginx加载了第三方模块出现内存增长,node_memory_MemAvailable_bytes会持续下降。结合node_memory_SwapUsed_bytes观察是否开始使用交换分区,一旦出现Swap使用,性能会断崖式下降。此时可以结合ps命令进一步定位具体进程。
下面给出两条Prometheus告警规则示例,分别用于主机内存不足和磁盘空间不足。规则文件通过rule_files加载到Prometheus中。
groups:
- name: nginx_host_alerts
rules:
- alert: HostMemoryLow
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10
for: 5m
labels:
severity: warning
annotations:
summary: "主机内存可用率低于10%"
description: "实例 {{ $labels.instance }} 当前可用内存仅 {{ $value }}%"
- alert: HostDiskSpaceLow
expr: node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"} * 100 < 10
for: 5m
labels:
severity: critical
annotations:
summary: "磁盘空间不足"
description: "实例 {{ $labels.instance }} 挂载点 {{ $labels.mountpoint }} 剩余空间不足10%"
上面的表达式中使用了<表示小于,注意在Prometheus配置文件中可以直接写<或者转义为<,PromQL本身支持。规则触发后可以通过Alertmanager发送邮件、企业微信或钉钉通知。
实际生产环境中,建议把node_exporter的--collector.disable-defaults和--collector.filesystem.ignored-mount-points等参数利用起来,过滤掉不需要的挂载点和设备,减少指标数量。同时为Prometheus设置合理的scrape_interval和retention.time,避免监控数据占用过多磁盘。

