nginx stream模块无法直接记录tcp连接建立时长和状态码,因其工作在传输层,需结合自定义日志、proxy_timeout错误日志、tcpdump/ebpf等系统工具协同实现逼近监测。

Stream 模块本身不记录日志中的“连接建立时长”或“状态码”,因为它工作在 TCP/UDP 层,没有 HTTP 的 status_code 概念,也不直接测量 TCP 握手耗时。但你可以通过组合 nginx 的 stream 模块 + 自定义日志格式 + 系统级辅助手段(如 tcpdump 或 eBPF)来逼近目标:监控特定 TCP 转发路径的连接建立延迟(SYN → SYN-ACK → ESTABLISHED)和连接终态(如正常关闭、RST、超时等)。
1. 用 stream_log_format 记录基础连接元数据
nginx stream 模块支持 log_format 和 access_log,可记录客户端 IP、后端地址、连接时间戳、字节数等。虽然不能直接记录“建立时长”,但可通过前后时间差估算(需配合 downstream 建立完成标记):
- 启用
stream { log_format main "... $time_iso8601 $remote_addr → $server_addr:$server_port ..."; } - 使用
$upstream_connect_time(仅当开启proxy_timeout且后端响应 SYN-ACK 后才生效)——注意:该变量在 stream 中实际支持有限,多数版本仅在 http 模块可用;stream 中更可靠的是$time_local和$upstream_addr - 推荐记录:
$remote_addr $server_addr $upstream_addr $time_iso8601 $bytes_sent $bytes_received $status(其中$status是伪状态,stream 不原生提供;需自行映射)
2. 用 proxy_timeout + error_log 捕获连接异常终态
stream 没有 HTTP 状态码,但可通过错误日志识别连接失败类型,间接反映“状态”:
- 设置合理
proxy_timeout 5s;,超时会触发upstream timed out日志 - 后端拒绝连接(RST)会记录
connection refused - 客户端中断会记录
connection reset by peer - 将这些错误重定向到独立日志文件:
error_log /var/log/nginx/stream-error.log warn;,再用 grep 或 filebeat 提取关键词
3. 补充手段获取真实建立时长(SYN-RTT)
nginx stream 无法精确测量 TCP 握手耗时(因内核完成三次握手后才通知应用层),必须借助外部工具:
- 用
tcpdump -i any port 8080 -nn -ttt抓包,过滤 SYN/SYN-ACK 时间戳,手动计算 RTT - 用
bpftrace或tcpretrans监控重传与连接建立事件(适合高精度场景) - 在 upstream 服务侧打点:例如后端服务在 accept() 返回后立即记录时间,与 nginx 记录的
$time_iso8601对比,可得“nginx 到后端建立延迟”(含内核队列等待)
4. 为特定转发路径打标并隔离日志
若需监控某组 IP 或端口的 TCP 路径,避免日志混杂:
- 用
match指令区分流量:match mysql { proxy_timeout 10s; proxy_pass backend_mysql; } - 为 match 块单独配置日志:
access_log /var/log/nginx/mysql-stream.log main; - 结合 geo 或 map 模块对 client IP 分类,再路由到不同 match 块,实现按源/目标打标
不复杂但容易忽略:stream 日志默认不记录连接关闭原因,也不暴露握手细节。真要监控建立时长和连接健康度,nginx 只能做边界观测,核心指标仍需系统层协同。











