nginx 实现请求级统计分析需依托自定义 access_log 输出原始请求数据(含耗时、状态码等),结合外部工具流式处理,辅以 stub_status 获取连接指标,openresty+lua 支持动态埋点,关键在于日志格式一致性与时间精度。

利用 Nginx 实现请求级统计分析,核心是借助其日志能力 + 可扩展模块(如 ngx_http_stub_status_module、ngx_http_log_module)+ 外部工具链,而非在 Nginx 内部做复杂聚合。Nginx 本身不提供实时请求维度的多维分析界面,但能精准输出每条请求的原始数据,这是统计分析的可靠起点。
启用并定制 access_log 获取请求级原始数据
Nginx 默认记录 access log,但默认格式信息有限。要支持请求级分析,需定义包含关键字段的自定义日志格式:
- 添加
$request_time(处理耗时)、$upstream_response_time(后端响应耗时)、$status(状态码)、$http_referer、$http_user_agent、$request_length、$bytes_sent等 - 示例配置:
log_format detailed '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$request_time $upstream_response_time ' '$request_length $bytes_sent'; - 在 server 或 location 块中启用:
access_log /var/log/nginx/access_detailed.log detailed; - 注意:日志写入有缓冲,默认可能延迟;生产环境建议加
buffer=64k flush=1s平衡性能与实时性
用 logrotate + 实时管道将日志送入分析工具
直接解析滚动日志文件效率低。更实用的方式是将 access_log 输出到 FIFO(命名管道)或 stdout,再由外部程序消费:
- 创建管道:
mkfifo /var/log/nginx/access_pipe - 配置 Nginx 日志输出到该管道:
access_log /var/log/nginx/access_pipe detailed; - 启动流式分析器监听管道,例如用 Python 脚本逐行解析、提取 IP/URL/耗时/状态码,写入 Redis Hash 或 Kafka Topic
- 也可用
tail -F /var/log/nginx/access.log | ...配合 awk/grep/jq(配合 JSON 日志)做轻量级实时统计,比如“每秒请求数”、“慢请求(>1s)占比”
结合 stub_status 模块获取基础连接级指标
ngx_http_stub_status_module 是内置模块,可暴露当前 worker 连接状态,适合监控但不替代请求级分析:
- 启用方式:在 server 块中添加
location /nginx_status { stub_status; allow 127.0.0.1; deny all; } - 返回内容如:
Active connections: 12<br>server accepts handled requests<br>15625 15625 32783<br>Reading: 0 Writing: 4 Waiting: 8
- 它反映瞬时连接数、总接受/处理/请求数,但无 URL、状态码、耗时等请求粒度信息 —— 仅作补充参考
进阶:用 OpenResty + Lua 做请求级实时埋点
若需在请求生命周期中动态采集(如按 Cookie 标记用户、按 Header 分渠道、记录上游异常原因),OpenResty 是更灵活的选择:
- 在
access_by_lua_block中读取ngx.var.arg_xxx、ngx.var.http_xxx、ngx.var.status(需配合log_by_lua_block获取最终状态) - 用
ngx.shared.DICT做内存计数(如按 path 统计 QPS),或调用resty.kafka发送结构化事件 - 示例:记录每个请求的 URI 和处理时间到共享字典(供 Prometheus 抓取)
log_by_lua_block { local dict = ngx.shared.stats local key = "req_" .. ngx.var.uri dict:incr(key, 1) } - 注意:Lua 逻辑需轻量,避免阻塞;高并发下优先走异步日志,而非同步上报
不复杂但容易忽略的是日志格式一致性与时间精度 —— 所有分析都依赖准确的时间戳和字段分隔。确保 log_format 中使用 $time_iso8601 或 $msec,并统一日志轮转策略,才能让后续的 ELK、Grafana Loki 或自研系统稳定解析每一条请求记录。











