Nginx 默认不支持按 server_name 的实时流量聚合,需编译安装 nginx-module-vts 模块,并在 server 块中配置 vhost_traffic_status_filter_by_set_key $server_name 才能实现域名维度统计。

直接说结论:Nginx 默认不提供按 server_name 维度的实时流量聚合视图,必须通过第三方模块 nginx-module-vts(VTS)实现;它不是开箱即用的“插件”,需要重新编译 Nginx,且默认统计路径(/status)不按 server_name 分组——得手动配 vhost_traffic_status_filter_by_set_key 才行。
为什么默认 /status 不显示每个 server_name 的独立流量?
VTS 模块默认只做全局和 upstream 级统计,server 块本身不自动注册为独立维度。即使你写了多个 server { server_name example.com; ... },所有请求都混在 nginx_status 的 serverZones 下的 ""(空字符串)里,根本看不到域名区分。
关键原因在于:VTS 不会自动把 server_name 当作分组 key,除非你显式告诉它用哪个变量来切片。
实操建议:
- 在对应
server块内添加vhost_traffic_status_filter_by_set_key $server_name server_name;—— 这句才是让 VTS 把该server的所有请求归到server_name标签下 - 必须配合
vhost_traffic_status_zone(通常写在http块)启用内存共享区,否则 filter 指令无效 -
$server_name是运行时变量,值为当前匹配成功的server_name(注意不是$host,后者可能被客户端篡改)
编译 Nginx 时漏掉 --add-dynamic-module 或没加载 so 文件,vhost_traffic_status 指令直接报错
常见错误现象:unknown directive "vhost_traffic_status",哪怕源码已下载、configure 参数看着也对。
核心问题出在动态模块加载链路上:
- 如果 configure 用了
--add-dynamic-module=../nginx-module-vts,编译后生成的是ngx_http_vhost_traffic_status_module.so,但 Nginx 不会自动加载它 - 必须在
nginx.conf的http或main上下文中显式写load_module modules/ngx_http_vhost_traffic_status_module.so; - 路径必须是相对于
nginx -t显示的prefix(比如/usr/local/nginx),不是源码路径 - 若用静态编译(
--add-module),则无需load_module,但升级模块要重编全部 Nginx
/status/format/json 返回数据里 serverZones 为空或只有 ""?
这说明请求根本没有命中你配置了 vhost_traffic_status_filter_by_set_key 的 server 块。典型场景有:
- 测试用的
curl -H 'Host: example.com' http://127.0.0.1/请求,却发到了 default server(没配server_name或server_name _),而那个 default block 没加 filter 指令 -
server_name写了通配符如*.example.com,但 VTS 的 filter key 不支持通配展开,只会存字面量*.example.com,导致统计名不可读 - HTTPS server 块没配
ssl_certificate,Nginx 启动失败,整个 block 被跳过,filter 指令自然不生效 - 用了
map或set改写$server_name,但 VTS filter 只认原始匹配值,不认重写后的变量
想看实时 QPS、带宽、状态码分布,但 JSON 数据太 raw 怎么办?
VTS 的 /status/format/json 是纯指标快照,没有计算逻辑。比如 “当前 QPS” 得靠客户端自己每秒拉两次,算差值;“响应时间 P95” 它根本不统计。
真正能用的方案只有两个:
- 前端轮询 + JS 计算:用
fetch('/status/format/json')拿两次requestCounter差值除以时间间隔,简单但不准(受采集周期抖动影响) - 后端代理聚合:用 Python/Node.js 起个轻量服务,定时拉 VTS 接口,存入 Redis 的 Sorted Set 或 TimescaleDB,再暴露 REST API 给 Grafana 查
- 别碰
/status/format/prometheus:它只暴露全局指标,不包含serverZones维度,VTS 官方明确不支持 Prometheus 多维导出
最易忽略的一点:VTS 的计数器是累计值(如 bytesIn),不是瞬时速率。所有“实时”视图都是二次加工结果,原始数据里根本没有 “QPS” 这个字段。


















