Nginx Stream模块高性能四层转发本质复用HTTP模块相同的epoll/kqueue事件循环,不解析协议、纯字节流透传,仅维护socket句柄与超时定时器,实现低延迟、无状态、轻量级TCP/UDP转发。

Nginx Stream 模块的高性能四层转发,本质不依赖“自定义事件循环”,而是深度复用 Nginx 主进程已有的 epoll/kqueue/iocp 事件驱动模型——它共享与 HTTP 模块完全相同的底层异步 I/O 调度机制,只是在协议处理层剥离了应用层解析逻辑,从而实现真正轻量、无状态、低延迟的透传。
stream 模块复用的是 Nginx 全局事件循环,不是独立实现
Nginx 启动后,worker 进程会初始化一个统一的事件循环(如 Linux 下默认为 epoll),这个循环同时驱动:
-
http块中所有监听端口的 HTTP/HTTPS 连接 -
stream块中所有监听端口的 TCP/UDP 连接 -
events配置定义的连接数、多路复用方式等全局参数
也就是说,你无需、也无法为 stream 单独配置或启动一个新事件循环。它的高性能来源于:
- 所有 socket 由同一组 worker 进程统一 accept、读写、超时管理
- 数据流不进入应用层解析(不 parse HTTP header、不 decode TLS record),直接 memcpy 转发
- 连接状态仅维护 socket 句柄、缓冲区和超时定时器,内存开销极小
TCP 转发:基于连接的零拷贝透传
当客户端建立 TCP 连接到 listen 3306; 的 server 块时:
- Nginx worker 接收 accept 事件,创建 client socket
- 根据
proxy_pass选择 upstream 中可用后端,发起非阻塞 connect - 连接就绪后,启用双向 read/write 事件监听
- 收到 client 数据 → 写入 backend socket 缓冲区;收到 backend 数据 → 写入 client socket 缓冲区
- 整个过程无协议解包、无内容检查、无重写,纯字节流搬运
典型调优参数直接影响事件循环效率:
-
worker_connections 4096;—— 单 worker 最大并发连接数,需与系统ulimit -n匹配 -
use epoll;—— 显式指定高效 I/O 多路复用模型(Linux) -
proxy_timeout 30s;—— 控制空闲连接在事件循环中驻留时长,避免 fd 泄漏 -
proxy_buffer_size 64k;—— 减少小包 syscall 次数,提升吞吐
UDP 转发:基于数据报的无连接事件分发
UDP 不维护连接状态,stream 模块采用“每个数据报独立处理”模式:
-
listen 53 udp;表示该 server 块只处理 UDP 报文 - 收到一个 UDP 包(最大 65507 字节)→ 解析源 IP:PORT → 查 upstream → 将整包转发至选定后端
- 不保证顺序、不重传、不合并多个请求,天然契合 DNS、Syslog、NTP 等无状态协议
关键限制也源于此模型:
- 无法做“会话保持”(如 ip_hash 对 UDP 无效,因无连接上下文)
-
proxy_responses 1;仅表示等待首个响应包即认为本次交互完成,不适用于需多次往返的 UDP 应用(如某些自定义协议) - 每个
server块只能声明一种协议(udp或无标识,默认 TCP),不可混用
真正的无状态,体现在配置与运行时两个层面
- 配置上:upstream 中各
server行不含 session 语义,不支持 cookie、header、path 等七层标识;健康检查仅靠max_fails/fail_timeout统计 connect 失败次数,不发业务探针 - 运行时:worker 进程崩溃不影响其他 worker;reload 时旧连接平滑关闭、新连接立即由新配置接管;无共享内存存储会话表或路由缓存
这种设计让 stream 模块在万级并发 MySQL 连接、十万 QPS DNS 查询等场景下,CPU 占用稳定低于 15%,P99 延迟控制在毫秒级。











