一、基础原理
Nginx分为七层HTTP模块(http{}) 和四层流模块(stream{})
http{}:解析HTTP协议,处理http/https、反向代理、静态资源stream{}:传输层四层代理,不对数据包做协议解析,纯粹透明转发TCP连接、UDP数据包
支持业务:MySQL、Redis、SSH、DNS、RDP、游戏端口、syslog、VPN端口、WebSocket、MQTT等所有TCP/UDP服务
版本门槛:nginx ≥ 1.9.13 正式支持stream模块
核心特点
- TCP:面向连接,Nginx维持客户端‑Nginx‑后端两条TCP连接
- UDP:无连接数据包,Nginx维护会话哈希表,相同五元组数据包转发至同一个后端
⚠️ 硬性语法:stream{} 必须和 http{} 同级,不能写在http大括号里面
二、检查Nginx是否支持stream模块
1、查看编译参数
bash
nginx -V 2>&1 | grep stream
- 输出
--with-stream→ 已经内置静态模块,可以直接使用 - 输出
--with-stream=dynamic→ 动态模块,需要手动加载 - 无任何输出 → 当前nginx不带stream模块
2、安装带stream模块的nginx
bash
# CentOS/RHEL
yum install nginx-mod-stream -y
# Ubuntu/Debian
apt install nginx-full -y
动态模块加载方式(nginx.conf最顶部)
nginx
load_module modules/ngx_stream_module.so;
三、最简入门示例
打开主配置文件 nginx.conf
3.1 TCP端口转发示例
本机3307端口,转发到后端MySQL 192.168.1.100:3306
nginx
stream {
server {
listen 3307;
proxy_pass 192.168.1.100:3306;
}
}
3.2 UDP端口转发示例(DNS 53端口)
listen后面必须添加 udp 参数,否则默认监听TCP
nginx
stream {
server {
listen 53 udp;
proxy_pass 223.5.5.5:53;
}
}
重载配置生效
bash
nginx -t
nginx -s reload
四、Upstream上游集群 & 负载均衡策略
适合多台后端服务器做四层负载均衡,TCP、UDP均可共用upstream
4.1 基础上游组
nginx
stream {
upstream mysql_group {
server 192.168.1.10:3306 weight=2;
server 192.168.1.11:3306 weight=1;
server 192.168.1.12:3306 backup; # 备用节点,全部主节点宕机才启用
}
server {
listen 3306;
proxy_pass mysql_group;
}
}
server后端参数说明
| 参数 | 作用 |
|---|---|
| weight=N | 权重,默认1;数值越高分配流量越多 |
| backup | 备份节点,平时不接收流量 |
| down | 标记节点永久下线 |
| max_fails=3 | 失败3次判定后端故障 |
| fail_timeout=30s | 故障之后30s不再探测该后端 |
4.2 五种负载均衡算法
写在upstream块内部
nginx
upstream backend {
#1.轮询(默认,无需配置)
server 127.0.0.1:8080;
#2.最少连接,优先分配给当前活跃连接最少后端,长连接业务首选MySQL/Redis
least_conn;
#3.IP哈希,同一个客户端IP固定转发一台后端,实现会话黏连
ip_hash;
#4.最短响应时间(Nginx‑Plus商业版)
least_time first_byte;
#5.自定义哈希
hash $remote_addr$remote_port consistent;
}
UDP无连接短包业务:优先轮询;TCP长连接数据库优先 least_conn
五、listen 完整高级参数详解
nginx
listen [ip]:port [参数列表];
常用全部参数:
nginx
# TCP示例
listen 0.0.0.0 2222 reuseport so_keepalive=on backlog=10000 proxy_protocol;
# UDP示例
listen 0.0.0.0:53 udp reuseport;
udp:开启udp数据包代理,没有就是tcpreuseport生产环境必加
Linux内核多端口复用,多个worker进程独立监听端口,减少锁竞争,高并发性能暴涨
so_keepalive=on
开启TCP保活,Nginx自动发送keepalive探测空闲断开的死连接,适合SSH、远程桌面长连接backlog=数值
TCP挂起连接队列上限,高并发调大至10000‑65535proxy_protocol
开启PROXY‑PROTOCOL协议;Nginx接收上层负载均衡器传来的真实客户端IPipv6only=on监听IPv6端口
nginx
listen [::]:3306;
六、stream代理核心指令大全(生产必配置)
6.1 超时参数(重中之重,绝大多数连接异常都是超时不合理)
nginx
server {
listen 3307;
proxy_pass mysql_group;
# 和后端建立TCP连接超时,TCP专用;UDP不需要握手,该参数无效
proxy_connect_timeout 3s;
# 空闲超时:两端长时间没有任何数据,则关闭代理会话
# MySQL长连接设置600s;DNS/UDP短包设置10s
proxy_timeout 300s;
}
6.2 缓冲区配置
nginx
# 数据包缓冲区大小;协议握手包很大时上调至64k
proxy_buffer_size 16k;
6.3 后端故障转移
nginx
# 连接失败、超时的时候自动切换下一台后端
proxy_next_upstream on;
# 故障转移最长耗时
proxy_next_upstream_timeout 10s;
# 最多尝试后端数量
proxy_next_upstream_tries 3;
6.4 UDP专属指令
nginx
server {
listen 53 udp;
proxy_pass 223.5.5.5:53;
# 等待后端返回UDP响应包数量
# 0=单向流量,不需要等待后端回复(syslog日志上报)
proxy_responses 1;
# UDP会话超时,无数据包之后销毁会话表
proxy_timeout 10s;
}
UDP原理:nginx维护一张五元组会话表;同一个客户端ip+port数据包路由至固定后端;proxy_timeout到期销毁会话。
6.5 客户端真实IP透传后端
四层TCP代理默认后端获取到的是Nginx内网IP;有两种方案
方式1:Proxy‑Protocol(推荐,MySQL/Redis/SSH全部支持)
nginx侧:
nginx
listen 3306 proxy_protocol;
然后后端服务开启proxy protocol解析客户端源IP
方式2(仅Nginx商业版)
proxy_set_header 只属于七层http模块,stream四层不能使用!
七、访问日志、错误日志配置
stream模块日志需要独立定义日志格式,和http日志互不通用
nginx
stream {
# 自定义日志格式
log_format stream_log '$remote_addr [$time_local] $protocol '
'$status $bytes_sent $bytes_received $session_time';
# 全局访问日志
access_log /var/log/nginx/stream-access.log stream_log buffer=64k;
error_log /var/log/nginx/stream-error.log warn;
server {
listen 3306;
proxy_pass 192.168.1.10:3306;
}
}
日志字段解释
- $protocol:TCP / UDP
- $status:会话状态
- $bytes_sent:nginx发给客户端字节
- $bytes_received:nginx收到客户端字节
- $session_time:连接存活时长
八、四层SSL透传 TLS‑Passthrough(HTTPS/SSL流量直接转发不解密)
适合后端自己处理SSL证书,Nginx只做四层流量转发、不做证书解密
nginx
stream {
upstream https_backend {
server 192.168.1.10:443;
}
server {
listen 443;
proxy_pass https_backend;
proxy_connect_timeout 5s;
proxy_timeout 3600s;
}
}
如果需要Nginx负责SSL加解密,则需要
proxy_ssl系列指令,属于Nginx高级TLS代理。
九、完整生产环境优化配置模板
nginx.conf主配置
nginx
# 开启stream动态模块(静态编译则删掉此行)
#load_module modules/ngx_stream_module.so;
worker_processes auto;
worker_rlimit_nofile 200000; # 文件句柄上限
events {
worker_connections 65535;
multi_accept on;
}
http {
# 此处放普通http网站配置,和四层代理互不干扰
}
# ==========四层TCP/UDP转发全部在这里==========
stream {
log_format stream_log '$remote_addr [$time_local] $protocol '
'$status $bytes_sent $bytes_received $session_time';
access_log /var/log/nginx/stream-access.log stream_log buffer=128k;
error_log /var/log/nginx/stream-error.log warn;
# MySQL集群
upstream mysql_cluster {
least_conn;
server 192.168.1.20:3306 max_fails=3 fail_timeout=20s;
server 192.168.1.21:3306 max_fails=3 fail_timeout=20s;
}
server {
listen 3306 reuseport so_keepalive=on backlog=20000;
proxy_pass mysql_cluster;
proxy_connect_timeout 3s;
proxy_timeout 600s;
proxy_buffer_size 32k;
}
# Redis TCP代理
server {
listen 6379 reuseport;
proxy_pass 192.168.1.30:6379;
proxy_connect_timeout 2s;
proxy_timeout 300s;
}
# DNS UDP 53端口
server {
listen 53 udp reuseport;
proxy_pass 223.5.5.5:53;
proxy_responses 1;
proxy_timeout 8s;
}
# SSH端口转发
server {
listen 2222 reuseport so_keepalive=on;
proxy_pass 192.168.1.50:22;
}
}
十、内核&操作系统性能优化(四层代理高并发必备)
1. sysctl.conf 内核参数优化
ini
# 打开端口复用、TIME‑WAIT快速回收
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 0
net.core.somaxconn = 65535
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
生效:sysctl -p
2、防火墙放行端口
bash
# firewalld
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --add-port=53/udp --permanent
firewall-cmd --reload
十一、常见问题排查清单
1、启动报错 unknown directive "stream"
原因:nginx没有stream模块
- yum安装nginx‑mod‑stream 或者加载动态模块
2、nginx可以ping通后端,但连接端口超时
- Nginx服务器防火墙拦截出站流量
- 后端服务器防火墙、安全组没有放行端口
- 后端服务仅监听127.0.0.1,没有监听0.0.0.0
检查后端监听:
ss -tulnp | grep 3306
3、UDP数据包收不到、时通时断
- listen必须带上udp关键字
- 缩短proxy_timeout,UDP会话超时销毁时间建议5‑15s
- 安全组同时放行udp协议
4、长连接过一会自动断开
调大 proxy_timeout;TCP开启 so_keepalive=on
5、负载均衡策略不生效
- least_conn 只针对TCP长连接有效;DNS这类一次性UDP短包几乎看不出效果
- ip_hash 依靠客户端IP,经过NAT之后所有客户端IP一致会造成流量倾斜
6、需要获取真实客户端IP
使用 listen xxx proxy_protocol;,后端开启proxy‑protocol支持
十二、stream和HAProxy、LVS简单对比
- Nginx‑Stream:配置简单,可以七层+四层一体化,适合中小型业务、混合协议网关;缺点高性能弱于LVS
- HAProxy:四层七层都很强,健康检查功能完善,适合数据库负载均衡
- LVS:纯内核态四层负载,性能最强,适合几十万以上超高并发UDP/TCP流量
适用场景总结
- Redis、MySQL、MQTT、SSH、RDP → Nginx‑TCP转发
- DNS、syslog日志、游戏数据包、语音数据包 → Nginx‑UDP转发
- 四层SSL透传、端口网关、多端口统一入口