nginx 1.13.2+ 的 stream 模块支持 $bytes_sent、$bytes_received、$session_time 等变量记录 tcp 连接指标,需在 stream 块内定义 log_format 并启用 access_log,变量仅在连接关闭后写入日志。

Nginx 的 stream 模块默认不支持像 http 模块那样直接使用 $bytes_sent、$request_time 等变量记录 TCP 连接的字节数和持续时间。但自 Nginx 1.13.2 起,stream 模块引入了 log_format 和部分内置变量,可在启用 access_log 的前提下记录连接级指标。
确认 Nginx 版本与 stream 日志支持
运行 nginx -v 确保版本 ≥ 1.13.2;低于此版本无法使用 $bytes_sent、$session_time 等变量。若为较新版本(如 1.19+),这些变量已稳定可用。
在 stream 块中定义日志格式
必须在 stream 上下文中(而非 http)定义 log_format,且需在 server 块外、stream 块内声明:
stream {
log_format basic '$remote_addr:$remote_port - $server_addr:$server_port '
'[$time_local] $protocol $status $bytes_sent $bytes_received '
'$session_time';
<pre class="brush:php;toolbar:false;">access_log /var/log/nginx/stream-access.log basic;
server {
listen 8080;
proxy_pass backend;
# 启用会话计时(必需)
proxy_timeout 30s;
}}
关键变量说明与注意事项
$bytes_sent:从 Nginx 发送给客户端的总字节数(即后端返回给客户端的数据量)
$bytes_received:从客户端接收的总字节数(即客户端发给后端的数据量)
$session_time:TCP 连接从建立到关闭的总秒数(浮点数,精度毫秒级)
$time_local:连接关闭时的时间戳(非连接开始时间)
- 所有变量仅在连接关闭后写入日志,因此日志是“事后记录”,无法实时统计
-
$session_time不等于$upstream_response_time(后者在http模块中,stream中不可用) - 若连接被异常中断(如超时、reset),
$bytes_sent和$bytes_received仍记录已实际传输的字节数 - 确保
proxy_timeout或tcp_nodelay等参数合理设置,避免连接挂起导致$session_time偏大
验证与调试建议
启用日志后,发起一次 TCP 连接(例如 telnet example.com 8080 并发送/接收数据后退出),检查日志是否输出类似:
192.168.1.100:54321 - 192.168.1.200:8080 [12/Jul/2024:10:25:33 +0000] TCP 200 1248 892 0.427
其中 1248 是发出字节,892 是接收字节,0.427 是连接持续约 427 毫秒。
若字段为空或为短横线(-),请检查:
– 是否在 stream 块内定义了 log_format
– 是否启用了 access_log(不是 error_log)
– 是否使用了旧版 Nginx(变量未定义)










