Nginx Stream模块实战:香港服务器TCP/UDP四层负载均衡与MySQL/Redis代理配置

Nginx Stream模块实战:香港服务器TCP/UDP四层负载均衡与MySQL/Redis代理配置

Nginx 广为人知的是 HTTP 七层代理,但它的 Stream 模块同样强大——可以在 TCP/UDP 四层对任意协议进行负载均衡和代理,无需理解上层协议内容。MySQL 读写分离代理、Redis Sentinel 的透明切换、游戏 UDP 服务器集群、数据库连接池前置代理,这些场景都能用 Nginx Stream 优雅解决,且几乎零额外资源开销。


一、Stream 模块 vs 七层 HTTP 代理

维度HTTP 代理(http block)Stream 模块(stream block)
工作层级L7(应用层,理解 HTTP)L4(传输层,透明转发字节流)
支持协议HTTP/HTTPS/WebSocket任意 TCP/UDP 协议
内容检查可以读取/修改 HTTP 头不解析内容,透明转发
典型用途Web 应用反向代理MySQL/Redis/游戏/DNS 代理
SSL 终结✅(SNI 分发)
性能开销极低(近乎零开销)

二、检查并编译 Stream 模块

<code"># 检查当前 Nginx 是否包含 Stream 模块
nginx -V 2>&1 | grep -o 'with-stream[^ ]*'
# 输出 --with-stream 说明已包含

# Ubuntu 安装带 Stream 的 Nginx
apt install -y nginx-full   # nginx-full 包含 Stream 模块
# 或
apt install -y nginx-extras
<code"># /etc/nginx/nginx.conf 顶层结构
# Stream 块与 http 块同级,不在 http 内部

# ... events 块 ...

http {
    # 普通 HTTP 配置
}

# Stream 模块配置(TCP/UDP 代理)
stream {
    # 日志格式
    log_format stream_basic '$remote_addr [$time_local] '
                            '$protocol $status $bytes_sent $bytes_received '
                            '$session_time "$upstream_addr"';
    access_log /var/log/nginx/stream.log stream_basic;

    include /etc/nginx/stream.d/*.conf;
}

三、MySQL 读写分离代理

<code"># /etc/nginx/stream.d/mysql.conf

upstream mysql_write {
    server 10.0.0.1:3306;    # 主库(写)
}

upstream mysql_read {
    server 10.0.0.1:3306 weight=1;   # 主库也可以读
    server 10.0.0.2:3306 weight=3;   # 从库1(读,权重更高)
    server 10.0.0.3:3306 weight=3;   # 从库2(读)

    # 健康检查(Nginx Plus 功能,开源版用 max_fails)
    # health_check interval=10 fails=3 passes=2;
}

# 写操作端口 3307 → 主库
server {
    listen 3307;
    proxy_pass mysql_write;
    proxy_connect_timeout 5s;
    proxy_timeout 300s;       # MySQL 长连接超时

    # 只允许应用服务器连接(IP 白名单)
    allow 10.0.0.0/24;
    deny all;
}

# 读操作端口 3308 → 从库集群
server {
    listen 3308;
    proxy_pass mysql_read;
    proxy_connect_timeout 5s;
    proxy_timeout 300s;

    allow 10.0.0.0/24;
    deny all;
}
<code"># 应用配置使用读写分离连接字符串(以 Python SQLAlchemy 为例)
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

# 写操作引擎(连接到 Nginx 写代理端口)
write_engine = create_engine(
    "mysql+pymysql://user:pass@nginx-proxy:3307/mydb",
    pool_size=10, pool_recycle=300
)

# 读操作引擎(连接到 Nginx 读代理端口)
read_engine = create_engine(
    "mysql+pymysql://user:pass@nginx-proxy:3308/mydb",
    pool_size=20, pool_recycle=300
)

四、Redis 主从透明代理

<code"># /etc/nginx/stream.d/redis.conf

upstream redis_master {
    server 10.0.0.4:6379;    # Redis 主节点
}

upstream redis_slaves {
    server 10.0.0.5:6379;    # 从节点1
    server 10.0.0.6:6379;    # 从节点2
    least_conn;               # 最少连接数调度
}

# 写操作(SET/DEL 等)→ 主节点
server {
    listen 6380;
    proxy_pass redis_master;
    proxy_connect_timeout 3s;
    proxy_timeout 60s;
    allow 10.0.0.0/24;
    deny all;
}

# 读操作(GET/KEYS 等)→ 从节点
server {
    listen 6381;
    proxy_pass redis_slaves;
    proxy_connect_timeout 3s;
    proxy_timeout 60s;
    allow 10.0.0.0/24;
    deny all;
}

五、TCP 负载均衡(游戏服务器)

<code"># /etc/nginx/stream.d/game.conf

upstream game_servers {
    server 10.0.1.1:7777 weight=1;
    server 10.0.1.2:7777 weight=1;
    server 10.0.1.3:7777 weight=1;

    # 会话保持:同一个客户端 IP 总是连接同一台游戏服务器
    hash $remote_addr consistent;
}

server {
    listen 7777;
    proxy_pass game_servers;
    proxy_connect_timeout 5s;
    proxy_timeout 3600s;    # 游戏长连接,超时设置长一些

    # 限制单 IP 并发连接数(防 CC 攻击)
    limit_conn_zone $remote_addr zone=game_conn:10m;
    limit_conn game_conn 5;    # 每个 IP 最多5个并发连接
}

六、UDP 负载均衡(DNS/游戏 UDP)

<code"># /etc/nginx/stream.d/udp.conf

upstream dns_servers {
    server 8.8.8.8:53;
    server 1.1.1.1:53;
}

server {
    listen 53 udp reuseport;    # UDP 协议,reuseport 提升性能
    proxy_pass dns_servers;
    proxy_timeout 3s;           # UDP 超时较短
    proxy_responses 1;          # 每个请求期望1个响应

    # UDP 游戏服务器(多个响应)
    # proxy_responses 0;        # 0 = 不限制响应数
}

七、SNI 分发(同端口多域名 TLS)

<code"># /etc/nginx/stream.d/tls-sni.conf
# 根据 TLS 握手的 SNI 信息将流量分发到不同后端
# 无需解密,保持端对端加密

map $ssl_preread_server_name $backend {
    api.yourdomain.com    10.0.0.10:443;    # API 服务器
    app.yourdomain.com    10.0.0.11:443;    # 应用服务器
    db-admin.yourdomain.com 10.0.0.12:443; # 数据库管理
    default               10.0.0.10:443;   # 默认
}

server {
    listen 443;
    ssl_preread on;          # 读取 SNI,不解密
    proxy_pass $backend;
    proxy_protocol on;       # 传递真实客户端 IP
}

八、连接数监控

<code"># 查看 Nginx Stream 当前连接状态
# 在 http 块中开启状态页
http {
    server {
        listen 8888;
        location /nginx_status {
            stub_status on;
            allow 127.0.0.1;
            deny all;
        }
    }
}

# 实时监控 TCP 连接
ss -tn state established | awk '{print $5}' | \
  grep -E ':3307|:3308|:6380|:7777' | \
  sort | uniq -c | sort -rn

九、总结

Nginx Stream 以极低的资源开销实现了 MySQL 读写分离路由、Redis 主从代理、游戏 UDP 负载均衡等场景,是架构设计中的”万能胶水层”。香港服务器上一台 Nginx 实例同时承担 HTTP 七层代理和 TCP/UDP 四层代理,统一管理所有流量入口,运维复杂度大幅降低。

Telegram