Nginx 接口耗时 Prometheus + Grafana 监控实施方案

汇报人:周晓玥


一、方案概述

1.1 监控目标

将 Nginx 代理的批量任务接口耗时数据($request_time$upstream_response_time、HTTP 状态码)接入 Prometheus + Grafana 监控体系,实现:

  • 各中心接口的请求耗时(P50/P95/P99)实时监控
  • 后端 upstream 响应耗时与 Nginx 代理延迟的对比
  • 异常接口自动告警(耗时突增、成功率下降)
  • 历史趋势分析(按小时/天/周维度聚合)

1.2 核心数据流

告警通知

Grafana 节点

Prometheus 节点

Nginx 节点 (2台)

每15s scrape

每15s scrape

规则评估

数据源

仪表盘

通知

通知

Nginx Master
9530端口

nginx-module-vts
指标暴露 :8080/metrics

Nginx Slave
9530端口

nginx-module-vts
指标暴露 :8080/metrics

Prometheus Server
指标采集 + 存储

Alertmanager
告警管理

Grafana Server
可视化 + 告警

企业微信

邮件

1.3 指标采集链路

Nginx请求 → nginx-module-vts 统计 → /metrics端点(JSON) 
  → Prometheus scrape → TSDB存储 
  → Grafana查询 → 仪表盘 + 告警

二、服务器规划

2.1 节点清单

角色主机名IP地址配置操作系统
Nginx Masterngx-batch-0110.1.92.614C8G / 100G SSDCentOS 7.9
Nginx Slavengx-batch-0210.1.92.624C8G / 100G SSDCentOS 7.9
Prometheusmon-prom-0110.1.92.1004C16G / 200G SSDCentOS 7.9
Grafanamon-grafana-0110.1.92.1014C8G / 100G SSDCentOS 7.9

注:若资源有限,Prometheus 和 Grafana 可合并部署在同一节点。

2.2 端口规划

服务端口说明防火墙策略
Nginx 业务端口9530批量任务流量入口允许 Control-M Agent 网段
nginx-module-vts metrics8080Prometheus 指标暴露允许 Prometheus 节点 IP
Prometheus Web UI9090Prometheus 管理界面允许运维网段
Grafana Web UI3000Grafana 管理界面允许运维网段
Alertmanager9093告警管理允许运维网段

2.3 存储规划

项目配置说明
Prometheus TSDB 存储路径/data/prometheus建议至少 200G,SSD
Prometheus 数据保留30d生产环境建议 30-90 天
Grafana 数据路径/var/lib/grafana不建议存放大文件
Nginx 日志路径/var/log/nginx建议配置 logrotate 定期切割

三、完整实施步骤

阶段一:Nginx 节点改造(ngx-batch-01 / ngx-batch-02)

Step 1:安装 nginx-module-vts 模块

知识点nginx-module-vts(Virtual Host Traffic Status)是一个第三方 Nginx 模块,可实时统计 Nginx 的请求量、耗时、状态码等指标,并通过 HTTP 接口暴露 Prometheus 格式的 metrics。

方案 A:重新编译 Nginx(推荐)

# 1. 下载 nginx-module-vts 模块
cd /usr/local/src
git clone https://github.com/vozlt/nginx-module-vts.git

# 2. 查看当前 Nginx 版本和编译参数
nginx -V
# 记录完整编译参数,例如:
# --prefix=/usr/local/nginx --add-module=../nginx-upsync-module ...

# 3. 重新编译 Nginx(追加 vts 模块)
cd /usr/local/src/nginx-1.24.0
./configure \
    --prefix=/usr/local/nginx \
    --add-module=../nginx-upsync-module \
    --add-module=../nginx-module-vts \    # 新增
    --with-http_realip_module \
    --with-http_ssl_module \
    --with-http_v2_module \
    --with-stream
make

# ⚠️ 注意:只执行 make,不要 make install(避免覆盖现有配置)
# 4. 备份原 Nginx 二进制
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak.$(date +%Y%m%d)

# 5. 替换二进制(平滑升级)
cp objs/nginx /usr/local/nginx/sbin/nginx

# 6. 平滑升级(不中断服务)
kill -USR2 $(cat /usr/local/nginx/logs/nginx.pid)
sleep 3
kill -WINCH $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
kill -QUIT $(cat /usr/local/nginx/logs/nginx.pid.oldbin)
sleep 3

# 7. 验证模块是否加载成功
nginx -V 2>&1 | grep nginx-module-vts
# 预期输出: --add-module=../nginx-module-vts

方案 B:动态模块加载(Nginx 1.11.5+)

# 编译为动态模块
./configure --add-dynamic-module=../nginx-module-vts
make modules

# 复制到模块目录
cp objs/ngx_http_vhost_traffic_status_module.so /usr/local/nginx/modules/

# 在 nginx.conf 顶部加载
# load_module modules/ngx_http_vhost_traffic_status_module.so;
Step 2:配置 nginx.conf

在现有 Nginx 配置中追加 vts 监控配置:

# =============================================
# nginx.conf 主配置文件
# =============================================

# 若使用动态模块
# load_module modules/ngx_http_vhost_traffic_status_module.so;

http {
    # =============================================
    # VTS 模块全局配置
    # =============================================
    
    # 开启 vts 统计功能
    vhost_traffic_status_zone;
    
    # 按过滤维度分组统计(关键:按接口路径分组)
    vhost_traffic_status_filter_by_host on;
    vhost_traffic_status_filter_by_set_key $location_name location::$1;
    
    # =============================================
    # 原有 upstream 和 location 配置保持不变
    # =============================================
    
    upstream batch_center {
        upsync 10.1.230.33:8848/nacos/v1/ns/instance/list?serviceName=corpor-batch ...;
        # ... 原有配置 ...
    }
    
    # 为每个 location 指定过滤标签
    server {
        listen 9530;
        
        # 设置 location 标签用于 vts 分组
        set $location_name "default";
        
        location /corpor-batch/ {
            set $location_name "corpor-batch";
            vhost_traffic_status_filter_by_set_key $location_name location::$1;
            
            proxy_pass http://batch_center;
            proxy_read_timeout 1800s;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
        }
        
        location /corpor-trans/ {
            set $location_name "corpor-trans";
            vhost_traffic_status_filter_by_set_key $location_name location::$1;
            
            proxy_pass http://trans_center;
            proxy_read_timeout 1800s;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
        }
        
        # ... 其他 location 类似 ...
        
        # =============================================
        # VTS 监控接口(仅限内网访问)
        # =============================================
        location /vts_status {
            vhost_traffic_status_display;
            vhost_traffic_status_display_format html;
            allow 10.1.0.0/16;
            allow 127.0.0.1;
            deny all;
        }
        
        # Prometheus metrics 格式接口
        location /metrics {
            vhost_traffic_status_display;
            vhost_traffic_status_display_format prometheus;
            allow 10.1.92.100;   # Prometheus 节点 IP
            allow 10.1.92.101;   # Grafana 节点 IP
            allow 127.0.0.1;
            deny all;
        }
        
        # 为 Prometheus 提供一个独立端口(可选,简化网络策略)
        # 在另一个 server 块中监听独立端口
    }
}

# =============================================
# 独立 metrics 端口(推荐:业务与监控端口分离)
# =============================================
server {
    listen 8080;
    server_name localhost;
    
    # 监控端口只暴露 metrics
    location /metrics {
        vhost_traffic_status_display;
        vhost_traffic_status_display_format prometheus;
        allow 10.1.92.100;
        allow 10.1.92.101;
        allow 127.0.0.1;
        deny all;
    }
    
    location /vts_status {
        vhost_traffic_status_display;
        vhost_traffic_status_display_format html;
        allow 10.1.0.0/16;
        allow 127.0.0.1;
        deny all;
    }
}
Step 3:验证 Nginx 指标暴露
# 重启 Nginx(或 reload)
nginx -s reload

# 验证模块统计启用
curl http://127.0.0.1:8080/vts_status
# 应返回 HTML 格式的流量统计页面

# 验证 Prometheus metrics 格式
curl http://127.0.0.1:8080/metrics
# 应返回类似以下内容:

Prometheus metrics 关键指标说明

# 请求总数(按状态码和 location 分组)
nginx_vts_server_requests_total{host="*",filter="location::corpor-batch"} 15234

# 请求速率
nginx_vts_server_request_seconds_total{...} 1256.789

# upstream 连接数
nginx_vts_upstream_request_seconds_total{...}

# 各状态码请求数(2xx / 3xx / 4xx / 5xx)
nginx_vts_server_requests_total{host="*",code="2xx",filter="location::corpor-batch"} 15100
nginx_vts_server_requests_total{host="*",code="5xx",filter="location::corpor-batch"} 34

# 平均响应时间(需计算)
# rate(nginx_vts_server_request_seconds_total[1m]) / rate(nginx_vts_server_requests_total[1m])

注意点:nginx-module-vts 暴露的是请求总耗时请求总数,需要 PromQL 做除法计算平均耗时。无法直接暴露 P95/P99 分位值,分位值需要在 Prometheus 中通过 histogram_quantile 计算。


阶段二:Prometheus 部署(mon-prom-01)

Step 1:安装 Prometheus
# 1. 创建用户
useradd --no-create-home --shell /bin/false prometheus

# 2. 下载 Prometheus(选择 LTS 稳定版)
cd /usr/local/src
wget https://github.com/prometheus/prometheus/releases/download/v2.52.0/prometheus-2.52.0.linux-amd64.tar.gz
tar -zxvf prometheus-2.52.0.linux-amd64.tar.gz

# 3. 安装
mkdir -p /etc/prometheus /data/prometheus
cp prometheus-2.52.0.linux-amd64/prometheus /usr/local/bin/
cp prometheus-2.52.0.linux-amd64/promtool /usr/local/bin/
cp -r prometheus-2.52.0.linux-amd64/consoles /etc/prometheus/
cp -r prometheus-2.52.0.linux-amd64/console_libraries /etc/prometheus/

chown -R prometheus:prometheus /etc/prometheus /data/prometheus
chmod +x /usr/local/bin/prometheus /usr/local/bin/promtool
Step 2:配置 prometheus.yml
# /etc/prometheus/prometheus.yml
global:
  scrape_interval: 15s          # 采集间隔
  scrape_timeout: 10s           # 采集超时
  evaluation_interval: 15s      # 告警规则评估间隔
  external_labels:
    env: production
    project: corporate-batch

# =============================================
# 告警规则文件
# =============================================
rule_files:
  - /etc/prometheus/rules/nginx_batch_alerts.yml

# =============================================
# 采集目标
# =============================================
scrape_configs:
  # Nginx Master 节点
  - job_name: 'nginx-batch-master'
    scrape_interval: 15s
    metrics_path: '/metrics'
    static_configs:
      - targets: ['10.1.92.61:8080']
        labels:
          instance: 'nginx-master'
          cluster: 'batch-cluster'
    
  # Nginx Slave 节点
  - job_name: 'nginx-batch-slave'
    scrape_interval: 15s
    metrics_path: '/metrics'
    static_configs:
      - targets: ['10.1.92.62:8080']
        labels:
          instance: 'nginx-slave'
          cluster: 'batch-cluster'
    
  # Prometheus 自身监控
  - job_name: 'prometheus'
    scrape_interval: 30s
    static_configs:
      - targets: ['localhost:9090']
Step 3:配置告警规则
# /etc/prometheus/rules/nginx_batch_alerts.yml
groups:
  - name: nginx_batch_alerts
    interval: 30s
    rules:
      # =============================================
      # 1. 接口平均耗时过高告警
      # =============================================
      - alert: NginxUpstreamAvgLatencyHigh
        expr: |
          (
            rate(nginx_vts_upstream_request_seconds_total{filter=~"location::.*"}[5m])
            /
            rate(nginx_vts_upstream_requests_total{filter=~"location::.*"}[5m])
          ) > 600
        for: 5m
        labels:
          severity: warning
          component: nginx-batch
        annotations:
          summary: "Nginx upstream 平均耗时过高"
          description: "Location {{ $labels.filter }} 最近5分钟 upstream 平均耗时 {{ $value | humanizeDuration }},可能影响批量任务执行"
      
      # =============================================
      # 2. 5xx 错误率告警
      # =============================================
      - alert: Nginx5xxErrorRateHigh
        expr: |
          (
            sum(rate(nginx_vts_server_requests_total{code="5xx",filter=~"location::.*"}[5m])) by (filter)
            /
            sum(rate(nginx_vts_server_requests_total{filter=~"location::.*"}[5m])) by (filter)
          ) > 0.01
        for: 3m
        labels:
          severity: critical
          component: nginx-batch
        annotations:
          summary: "Nginx 5xx 错误率超过 1%"
          description: "Location {{ $labels.filter }} 5xx 错误率 {{ $value | humanizePercentage }},可能存在后端服务故障"
      
      # =============================================
      # 3. 上游后端实例不可用告警
      # =============================================
      - alert: NginxUpstreamDown
        expr: |
          nginx_vts_upstream_server_up{backend=~".*"} == 0
        for: 2m
        labels:
          severity: critical
          component: nginx-batch
        annotations:
          summary: "Nginx upstream 后端实例不可用"
          description: "后端 {{ $labels.backend }} 健康检查失败超过 2 分钟"
      
      # =============================================
      # 4. 请求量异常下降告警
      # =============================================
      - alert: NginxRequestRateDrop
        expr: |
          (
            rate(nginx_vts_server_requests_total{filter=~"location::.*"}[10m])
            /
            rate(nginx_vts_server_requests_total{filter=~"location::.*"}[10m] offset 1h)
          ) < 0.1
        for: 10m
        labels:
          severity: warning
          component: nginx-batch
        annotations:
          summary: "Nginx 请求量异常下降"
          description: "Location {{ $labels.filter }} 请求量较 1 小时前下降超过 90%"
      
      # =============================================
      # 5. Prometheus 采集目标不可达告警
      # =============================================
      - alert: PrometheusTargetDown
        expr: up{job=~"nginx-batch.*"} == 0
        for: 2m
        labels:
          severity: critical
          component: prometheus
        annotations:
          summary: "Prometheus 采集目标不可达"
          description: "采集目标 {{ $labels.instance }} 不可达超过 2 分钟"
Step 4:配置 Alertmanager
# /etc/prometheus/alertmanager.yml
global:
  resolve_timeout: 5m

# 企业微信告警
route:
  group_by: ['alertname', 'component']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'wechat'
  routes:
    - match:
        severity: critical
      receiver: 'wechat-critical'
      repeat_interval: 30m

receivers:
  - name: 'wechat'
    wechat_configs:
      - corp_id: 'your_corp_id'
        to_party: '运维组'
        agent_id: '1000002'
        api_secret: 'your_secret'
        send_resolved: true
  
  - name: 'wechat-critical'
    wechat_configs:
      - corp_id: 'your_corp_id'
        to_user: '@all'
        agent_id: '1000002'
        api_secret: 'your_secret'
        send_resolved: true

  - name: 'email'
    email_configs:
      - to: 'ops-team@corp.com'
        from: 'alertmanager@corp.com'
        smarthost: 'smtp.corp.com:25'
        send_resolved: true
Step 5:启动 Prometheus
# 1. 创建 systemd 服务
cat > /etc/systemd/system/prometheus.service << 'EOF'
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
    --config.file=/etc/prometheus/prometheus.yml \
    --storage.tsdb.path=/data/prometheus \
    --storage.tsdb.retention.time=30d \
    --storage.tsdb.retention.size=150GB \
    --web.listen-address=0.0.0.0:9090 \
    --web.enable-lifecycle \
    --web.enable-admin-api \
    --storage.tsdb.wal-compression
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=10s
LimitNOFILE=65535

[Install]
WantedBy=multi-user.target
EOF

# 2. 启动
systemctl daemon-reload
systemctl enable prometheus
systemctl start prometheus
systemctl status prometheus

# 3. 验证
curl http://127.0.0.1:9090/api/v1/targets | python -m json.tool | grep "health"
# 预期看到所有 target 状态为 "up"
Step 6:启动 Alertmanager
# 创建 systemd 服务
cat > /etc/systemd/system/alertmanager.service << 'EOF'
[Unit]
Description=Alertmanager
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/alertmanager \
    --config.file=/etc/prometheus/alertmanager.yml \
    --storage.path=/data/alertmanager \
    --web.listen-address=0.0.0.0:9093
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target
EOF

mkdir -p /data/alertmanager
chown -R prometheus:prometheus /data/alertmanager

systemctl daemon-reload
systemctl enable alertmanager
systemctl start alertmanager

阶段三:Grafana 部署(mon-grafana-01)

Step 1:安装 Grafana
# 1. 添加 Grafana 官方 YUM 源
cat > /etc/yum.repos.d/grafana.repo << 'EOF'
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF

# 2. 安装
yum install -y grafana

# 3. 启动
systemctl daemon-reload
systemctl enable grafana-server
systemctl start grafana-server
systemctl status grafana-server

# 4. 开放防火墙
firewall-cmd --permanent --add-port=3000/tcp
firewall-cmd --reload
Step 2:配置数据源
# 1. 登录 Grafana(默认账户 admin/admin,首次登录会要求修改密码)
# http://10.1.92.101:3000

# 2. 添加 Prometheus 数据源
# Configuration → Data Sources → Add data source → Prometheus
# URL: http://10.1.92.100:9090
# Scrape interval: 15s
# 点击 Save & Test

也可通过 API 配置:

curl -X POST http://admin:admin@10.1.92.101:3000/api/datasources \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Prometheus",
    "type": "prometheus",
    "url": "http://10.1.92.100:9090",
    "access": "proxy",
    "isDefault": true
  }'
Step 3:仪表盘设计

在 Grafana 中创建以下仪表盘(或者导入预置 JSON):

仪表盘一:Nginx 批量任务总览

面板类型PromQL描述
全局 QPSStatsum(rate(nginx_vts_server_requests_total{filter=~"location::.*"}[1m]))所有批量任务每秒请求数
5xx 错误率Stat(sum(rate(nginx_vts_server_requests_total{code="5xx"}[5m])) / sum(rate(nginx_vts_server_requests_total[5m]))) * 1005xx 错误百分比
请求量时序Graphsum(rate(nginx_vts_server_requests_total{filter="$location"}[5m])) by (code)按状态码的请求量趋势
各中心平均耗时Table见下方说明各 Location 平均 upstream 耗时

各中心平均耗时 PromQL

# 按 Location 分组的平均 upstream 响应时间(秒)
(
  rate(nginx_vts_upstream_request_seconds_total{filter=~"location::.*"}[5m])
  /
  rate(nginx_vts_upstream_requests_total{filter=~"location::.*"}[5m])
)

# 转换为毫秒
(
  rate(nginx_vts_upstream_request_seconds_total{filter=~"location::.*"}[5m])
  /
  rate(nginx_vts_upstream_requests_total{filter=~"location::.*"}[5m])
) * 1000

仪表盘二:单中心任务耗时详情

使用 Grafana 变量 $location 动态切换:

# 变量定义
label_values(nginx_vts_server_requests_total{filter=~"location::.*"}, filter)

# 上游耗时速率(请求秒数/秒)
rate(nginx_vts_upstream_request_seconds_total{filter="$location"}[1m])

# 请求速率
rate(nginx_vts_upstream_requests_total{filter="$location"}[1m])

# 上游平均响应时间(毫秒)
(
  rate(nginx_vts_upstream_request_seconds_total{filter="$location"}[5m])
  / 
  rate(nginx_vts_upstream_requests_total{filter="$location"}[5m])
) * 1000

仪表盘三:Nginx 节点健康状态

面板PromQL描述
Nginx 节点存活up{job=~"nginx-batch.*"}1=存活 0=不可达
上游后端存活nginx_vts_upstream_server_up各后端实例健康状态
上游后端权重nginx_vts_upstream_server_weight当前权重
当前连接数nginx_vts_main_connections{filter="active"}活跃连接数
连接数变化rate(nginx_vts_main_connections{filter="accepted"}[1m])新建连接速率
Step 4:Grafana 告警配置

在 Grafana 中也可以设置告警(比 Prometheus Alertmanager 更适合业务人员):

# Grafana 告警渠道配置
# Alerting → Notification channels → Add channel

# 企业微信
Type: WeCom (企业微信)
Name: WeChat-Ops
Webhook URL: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx

# 邮件
Type: Email
Name: Email-Ops
Addresses: ops-team@corp.com

四、架构总览

被监控业务

通知层

可视化层

指标存储与告警层

数据采集层

负载均衡

负载均衡

负载均衡

scrape /metrics

scrape /metrics

规则评估

数据源

告警通知

告警通知

仪表盘告警

仪表盘告警

Nginx Master
10.1.92.61:9530

Nginx Slave
10.1.92.62:9530

nginx-module-vts
:8080/metrics

nginx-module-vts
:8080/metrics

Prometheus Server
10.1.92.100:9090
TSDB 存储 30d

Alertmanager
:9093
告警分组/去重/路由

Grafana
10.1.92.101:3000
仪表盘 + 告警

企业微信

邮件

批量中心
corpor-batch 64条任务

交易中心
corpor-trans 23条

其他中心
14条


五、关键 PromQL 查询清单

5.1 接口耗时类

# 1. 各中心上游平均耗时(毫秒)
(
  rate(nginx_vts_upstream_request_seconds_total{filter=~"location::.*"}[5m])
  /
  rate(nginx_vts_upstream_requests_total{filter=~"location::.*"}[5m])
) * 1000

# 2. 指定中心最近 1 小时平均耗时趋势(毫秒)
(
  rate(nginx_vts_upstream_request_seconds_total{filter="location::corpor-batch"}[5m])
  /
  rate(nginx_vts_upstream_requests_total{filter="location::corpor-batch"}[5m])
) * 1000

# 3. Nginx 端到端耗时 vs 上游耗时对比
# 端到端: (rate(nginx_vts_server_request_seconds_total[5m]) / rate(nginx_vts_server_requests_total[5m])) * 1000
# 上游:   (rate(nginx_vts_upstream_request_seconds_total[5m]) / rate(nginx_vts_upstream_requests_total[5m])) * 1000
# 代理延迟: 端到端 - 上游

5.2 请求量类

# 4. 各中心 QPS
sum(rate(nginx_vts_server_requests_total{filter=~"location::.*"}[1m])) by (filter)

# 5. 按状态码的 QPS
sum(rate(nginx_vts_server_requests_total{filter=~"location::.*"}[1m])) by (code)

# 6. 总请求量(过去 1 小时)
sum(increase(nginx_vts_server_requests_total{filter=~"location::.*"}[1h]))

5.3 错误率类

# 7. 各中心 5xx 错误率(百分比)
(
  sum(rate(nginx_vts_server_requests_total{code="5xx",filter=~"location::.*"}[5m])) by (filter)
  /
  sum(rate(nginx_vts_server_requests_total{filter=~"location::.*"}[5m])) by (filter)
) * 100

# 8. 各中心 4xx 错误率(百分比)
(
  sum(rate(nginx_vts_server_requests_total{code="4xx",filter=~"location::.*"}[5m])) by (filter)
  /
  sum(rate(nginx_vts_server_requests_total{filter=~"location::.*"}[5m])) by (filter)
) * 100

5.4 健康检查类

# 9. 采集目标存活状态
up{job=~"nginx-batch.*"}

# 10. 上游后端存活状态(按后端 server 分组)
nginx_vts_upstream_server_up

# 11. 上游后端当前权重
nginx_vts_upstream_server_weight

六、知识点与注意事项

6.1 nginx-module-vts 工作原理

概念说明
统计时机每次请求结束时,vts 模块通过 Nginx 的 log_subrequest 阶段钩子收集指标
内存开销所有统计(计数器/累加器)存储在共享内存中,各 Worker 进程共享,内存占用约 2MB~10MB
对象分级server(server 级别)→ filter(过滤标签级别)→ upstream(上游后端级别)→ upstream server(单后端实例级别)
指标类型仅暴露 Counter(计数器),无直接 Histogram/Summary,分位值需通过 PromQL 间接计算
性能影响< 1% CPU 开销,基本可忽略

6.2 vts 模块的局限性及应对

局限性表现应对方案
无原生分位值只能计算平均值,无法直接获得 P95/P99启用 Nginx $request_time 日志 + Loki/mtail 补充分位值计算
Counter 重置Nginx reload 后计数器归零Prometheus rate() 函数自动处理 Counter 重置
长时任务统计超长连接(>30min)的耗时计入该时间窗口通过 Grafana 变量选择合适时间窗口
无法按接口粒度过细vts filter 维度过多会增加内存开销按 Location 中心粒度统计即可,不做过细的 filter

6.3 编译模块注意事项

  1. 版本匹配:nginx-module-vts 必须与 Nginx 版本匹配,使用前查看模块的 README 确认兼容版本
  2. 编译依赖:需要 gccmakepcre-developenssl-develzlib-devel
  3. 平滑升级:使用 kill -USR2 信号实现二进制热替换,避免中断服务
  4. 保留旧 bin:升级前务必备份 nginx 二进制和配置
  5. 与 upsync 模块共存:nginx-module-vts 与 nginx-upsync-module 无冲突,可以同时编译

6.4 Prometheus 配置注意事项

  1. scrape_interval 不宜过短:15s 是推荐值,过短会增加 Nginx 和 Prometheus 压力
  2. 保留时间:30d 保留时间,建议存储空间 ≥ 150GB(取决于指标量)
  3. WAL 压缩--storage.tsdb.wal-compression 减少磁盘 I/O
  4. 生命周期管理--web.enable-lifecycle 允许 API 热重载配置(curl -X POST http://localhost:9090/-/reload
  5. 远程写入:生产环境建议配置 remote_write 到长期存储(如 VictoriaMetrics、Thanos)

6.5 Grafana 配置注意事项

  1. 数据源缓存:建议设置 Min time interval 为采集间隔(15s),避免查询粒度小于实际数据精度
  2. 模板变量:使用 $location 变量实现仪表盘复用,无需为每个中心单独创建面板
  3. 查询超时:复杂 PromQL 查询可能超时,建议在面板中设置合理的 Max data points
  4. 版本管理:将仪表盘 JSON 导出到 Git 仓库,实现配置版本管理

七、可能存在的问题及解决方案

7.1 编译问题

问题现象解决方案
模块不兼容nginx: [emerg] unknown directive "vhost_traffic_status_zone"确认模块已正确编译进 Nginx;检查 nginx -V 输出
编译错误make 报错缺少依赖yum install -y gcc make pcre-devel openssl-devel zlib-devel
多模块冲突与已有第三方模块冲突调整 ./configure 中模块加载顺序,先加载 vts 再加载 upsync
Nginx 版本不匹配版本不一致导致编译失败nginx -v 查看当前版本,下载对应版本的 Nginx 源码

7.2 运行时问题

问题现象解决方案
metrics 接口 403curl /metrics 返回 403检查 allow/deny 规则,确认 Prometheus 节点 IP 在白名单
vts 无数据/vts_status 页面显示空白或 0确认 vhost_traffic_status_zone; 在 http 块中;检查是否有实际请求经过
内存泄漏Nginx 内存持续增长vts 共享内存大小默认足够,若大量 filter 标签可限制 vhost_traffic_status_filter_max_node
reload 丢指标Nginx reload 后 Counter 归零Prometheus rate() 函数自动处理 reset,3 个采集周期后恢复正常

7.3 Prometheus 问题

问题现象解决方案
target downPrometheus 显示 target 状态为 DOWN检查网络连通性、防火墙规则、Nginx metrics 端口是否监听
磁盘空间不足Prometheus OOM 或 crash调整 --storage.tsdb.retention.size;增加磁盘空间;清理旧 WAL
大量时间序列查询变慢,内存飙升减少 filter 标签维度;使用 relabel_configs 丢弃不必要的标签
告警不生效规则配了但不触发检查 evaluation_interval;用 Prometheus UI 的 Alerts 页面验证规则表达式

7.4 Grafana 问题

问题现象解决方案
数据为空面板显示 “No data”检查 Prometheus 数据源连接;验证 PromQL 语法;确认时间范围有数据
查询超时面板加载很慢或超时减少查询时间范围或降低 Step 精度;拆分复杂面板
分位值不准计算的耗时显示为 0 或异常确认 Counter 累加正常;使用 increase() 代替 rate() 对比验证
Grafana 仪表盘不自动刷新数据显示陈旧检查面板右上角自动刷新设置;确认浏览器标签页保持活跃

7.5 高可用问题

问题现象解决方案
Prometheus 单点故障Prometheus 宕机,监控中断部署 2 台 Prometheus,配合 Thanos/Cortex 实现高可用
Grafana 单点故障Grafana 宕机,仪表盘不可见使用数据库(MySQL/PostgreSQL)后端 + 多实例部署
Nginx 节点故障某节点 metrics 不可达Prometheus 可以区分不同节点指标,不影响其他节点监控

八、验证清单

8.1 部署后验证

# 1. 验证 Nginx vts 模块
curl http://10.1.92.61:8080/metrics | head -20
# 应输出 Prometheus 格式的指标,包含 nginx_vts_ 开头

# 2. 验证 Prometheus 采集
curl http://10.1.92.100:9090/api/v1/targets 2>/dev/null | python -m json.tool | grep -E '"job"|"health"'
# 所有 target 的 health 应为 "up"

# 3. 验证指标可查询
curl -s 'http://10.1.92.100:9090/api/v1/query?query=nginx_vts_server_requests_total' | python -m json.tool | head -30

# 4. 验证 Grafana 数据源
curl http://admin:admin@10.1.92.101:3000/api/datasources/1 | python -m json.tool

# 5. 模拟批量请求验证耗时指标
for i in {1..100}; do
  curl -s -o /dev/null -w "%{http_code}\n" \
    --connect-timeout 30 --max-time 7200 \
    "http://10.1.92.60:9530/corpor-batch/xxx" &
done
wait

# 等待 30s 后查看 vts 数据
curl http://10.1.92.61:8080/metrics | grep 'location::corpor-batch'

8.2 验收标准

验收项通过标准
Nginx metrics 正常暴露curl /metrics 返回 200 + 包含 nginx_vts_* 指标
Prometheus 采集正常Targets 页面所有节点状态为 UP
Grafana 数据可见仪表盘可正确显示各中心耗时趋势图表
告警规则正常手动触发告警条件后能在 Alertmanager/企业微信收到通知
性能影响可控Nginx CPU 增加 < 1%,内存增加 < 10MB

九、总结

本方案通过 nginx-module-vts + Prometheus + Grafana 三层架构实现 Nginx 接口耗时的完整监控体系:

  1. nginx-module-vts:在 Nginx 侧零侵入地采集请求量、耗时、状态码等指标,通过 /metrics 接口暴露
  2. Prometheus:定时拉取 metrics,存储时序数据,执行告警规则
  3. Grafana:通过 PromQL 查询构建可视化仪表盘,实现实时监控和历史趋势分析
  4. Alertmanager:告警分组、去重、路由到企业微信/邮件

核心数据流Nginx 请求 → vts 统计 → /metrics → Prometheus scrape → Grafana 可视化 + Alertmanager 告警

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐