nginx 实现 tcp 代理负载均衡需启用 stream 模块,在顶层 stream 块中配置 upstream 和 server,支持 least_conn、hash $remote_addr consistent 等算法,并调优 proxy_connect_timeout、proxy_timeout 等参数以适配长连接场景。

要在 Nginx 中实现 TCP 代理的负载均衡,核心是启用 stream 模块并正确组织 upstream 与 server 块。它不走 HTTP 流程,而是直接在四层(传输层)转发原始 TCP 流量,适用于 MySQL、Redis、IM、SSH 等长连接服务。
确认 Nginx 支持 stream 模块
官方开源版 Nginx 1.9.0+ 已内置 stream 模块,但需编译时启用(默认多数发行版已开启)。验证方式:
- 运行
nginx -V 2>&1 | grep -o with-stream,输出含with-stream表示支持 - 若缺失,需重新编译并添加
--with-stream参数
基础 TCP 负载均衡配置结构
所有 TCP 相关配置必须放在顶层 stream { ... } 块中(与 http 平级),不能嵌套在 http 内。典型结构如下:
-
upstream 块:定义后端服务器组,支持
weight、max_fails、fail_timeout、backup等参数 -
server 块:监听客户端 TCP 端口,通过
proxy_pass指向 upstream 名称 -
关键代理指令:如
proxy_connect_timeout、proxy_timeout、proxy_socket_keepalive
示例(代理 Redis 端口 6379):
stream {
upstream redis_backend {
server 192.168.1.10:6379 weight=3 max_fails=2 fail_timeout=30s;
server 192.168.1.11:6379 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.12:6379 backup;
}
server {
listen 6379;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass redis_backend;
}
}
按业务选对调度算法
TCP 是长连接,算法选择直接影响连接驻留均衡性,不能只套用 HTTP 经验:
-
数据库/缓存类(MySQL、Redis):用
least_conn——新连接优先发给当前活跃连接数最少的节点,避免空闲连接堆积在某台机器上 -
IM 或 WebSocket 类服务:禁用
ip_hash(NAT 下失效),改用hash $remote_addr consistent;实现客户端亲和性 -
异构集群(新旧机器混布):结合
least_conn+weight,例如高性能节点设weight=10,老旧节点设weight=4
必须调优的连接生命周期参数
TCP 连接持续时间远长于 HTTP 请求,超时与健康检查设置不当会导致故障节点滞留连接或误判:
-
proxy_connect_timeout:建议 1–2 秒,配合max_fails=3 fail_timeout=30s快速摘除不可达节点 -
proxy_timeout:应略大于后端业务最大处理耗时(如 Redis 批量操作约 8 秒),但不宜超过 60 秒,否则拖慢故障恢复 -
proxy_socket_keepalive on:开启后可复用底层 socket,减少 TIME_WAIT 和握手开销,尤其利于高频短连场景 - 如后端支持连接池(如 MySQL 8.0+),可在 upstream 中加
keepalive 32;复用连接
验证与可观测性建议
仅靠配置生效不够,需确认连接真实分发效果:
- 用
ss -tn sport = :6379查看 Nginx 监听端口上的 ESTABLISHED 连接数 - 在
stream块中启用自定义日志:log_format tcp_log '$remote_addr [$time_local] $upstream_addr $upstream_connect_time';,再在 server 块中引用 - 结合
netstat -tn | grep :6379 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c分析客户端 IP 分布,排查爬虫或单点压测干扰











