用 $body_bytes_sent 实现轻量级吞吐与状态码监控,绕开 access_log 磁盘 i/o,仅记录时间、状态码、响应体大小、上游耗时、uri 和客户端 ip;结合 map 分组/采样、/dev/shm 或 syslog 输出、stub_status 实时观测及 buffer/flush 批量写入,兼顾低开销与数据精度。

直接用 $body_bytes_sent 做轻量级吞吐与状态码监控,核心是绕开完整请求日志(access log)的磁盘 I/O 和格式化开销,只在必要时记录关键指标,同时保留原始响应数据粒度。
用 $body_bytes_sent 替代 access_log 的关键逻辑
$body_bytes_sent 是 Nginx 在响应发送完成后才确定的变量,它只统计实际发给客户端的响应体字节数(不含响应头),天然适配“真实吞吐”场景。相比 $bytes_sent(含响应头),它更贴近业务侧关心的有效载荷。不写 access_log,而是通过 log_format + access_log 的条件写入,或搭配 map + if 实现按需采样/过滤。
构建低开销的吞吐与状态码聚合日志
- 定义精简日志格式,仅包含时间、状态码、响应体大小、上游耗时(
$upstream_response_time)、URI 路径($request_uri)和客户端 IP($remote_addr) - 用
map将状态码分组(如 2xx/4xx/5xx),便于后续按类别统计;也可用map控制采样率(例如只记录 5xx 或 >1MB 响应) - 将日志输出到内存文件系统(如
/dev/shm)或通过syslog推送到远程 collector,避免本地磁盘瓶颈
结合 stub_status 模块做实时状态观测
stub_status 提供瞬时连接数、处理请求数、已接受/已处理连接等基础指标,配合 $body_bytes_sent 日志可形成“宏观活跃度 + 微观响应质量”的双层视图。例如:当 Active connections 高但平均 $body_bytes_sent 显著下降,可能预示大量小响应(如 401/404)或异常中断;若 5xx 状态码对应的大体积响应突增,则指向后端服务降级。
用 log\_format + buffer + flush 控制写入节奏
- 启用
buffer和flush参数,例如access_log /var/log/nginx/metric.log main buffer=64k flush=1s;,把高频小日志聚合成批次写入,降低 syscall 次数 - 避免在
if块中直接使用access_log(Nginx 不支持),改用map定义日志开关变量,再在log_format中引用该变量实现条件日志 - 注意:
$body_bytes_sent在日志写入时才可用,不能用于rewrite或return等阶段,仅适用于log_format和access_log
不复杂但容易忽略的是变量生命周期和写入时机——它不是实时值,而是响应结束后的终态快照,正因如此才稳定可靠,也正因如此不能用于实时限流或动态决策。











