小易说IT 小易说IT

Nginx Stream TCP 四层负载均衡(MySQL 集群)完整配置

说明:

  1. stream {} 模块属于四层 TCP 负载均衡,工作在传输层,不解析 HTTP;用来代理 MySQL、Redis、SSH 等 TCP 协议。

  2. 需要编译 Nginx 时带上 --with-stream,否则不支持 stream 模块;stream{}http{} 同级,不能写在 http 里面!

  3. stream upstream 支持策略:轮询、加权轮询、least_conn、ip_hash;不支持 url_hash

  4. 健康检查:原生被动健康检查;主动健康检查需要 Nginx Plus / 第三方 ngx_stream_upstream_check_module

完整 nginx.conf 示例

worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
    worker_connections  1024;
}

# ========== stream 四层TCP负载均衡,和http{}同级 ==========
stream {
    upstream mysql_cluster {
        # 策略:least_conn 最少连接,MySQL推荐!
        least_conn;

        # MySQL后端节点,端口3306
        server 10.0.1.10:3306 weight=5 max_fails=3 fail_timeout=30s;
        server 10.0.1.11:3306 weight=3 max_fails=3 fail_timeout=30s;
        server 10.0.1.12:3306 weight=2 max_fails=3 fail_timeout=30s;
        # 备用节点,所有主节点不可用才启用
        server 10.0.1.13:3306 backup;
    }

    # 全局stream日志,方便排查连接问题
    log_format proxy_stream '$remote_addr [$time_local] '
        '$protocol $status $bytes_sent $bytes_received '
        '$session_time "$upstream_addr" '
        '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';

    access_log /var/log/nginx/stream-access.log proxy_stream;

    # 监听3306端口,对外提供MySQL连接入口
    server {
        listen 3306;
        proxy_pass mysql_cluster;

        # TCP代理超时参数,MySQL调优重点
        proxy_connect_timeout 10s;     # 连接后端MySQL超时
        proxy_timeout 600s;            # 连接空闲超时,600s无数据自动断开

        # TCP缓冲区
        proxy_buffer_size 16k;
    }
}

# ========== http模块(独立,放Web服务,和stream互不干扰) ==========
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
    }
}

参数详解(stream upstream)

upstream mysql_cluster {
    least_conn; # ✅ MySQL推荐:最少连接。慢查询会占用连接,轮询容易堆在同一个节点
    # ip_hash; # 如需同一个客户端IP固定连同一个MySQL节点,打开这个,注释least_conn
    server 10.0.1.10:3306 weight=5 max_fails=3 fail_timeout=30s;
}
  • max_fails=3:连续 3 次连接失败,标记节点不可用

  • fail_timeout=30s:标记失败后,30 秒内不再尝试访问该节点;30s 后重试探测

  • weight:权重,加权轮询模式生效

  • backup:备用节点,主节点全部 down 才启用

  • down:手动标记节点下线,用于维护:server 10.0.1.10:3306 down;

stream 支持的调度策略:

  • 默认:轮询 RR

  • least_conn:最少连接(MySQL/Redis 首选)

  • ip_hash:源 IP 哈希,同一个客户端 IP 固定打到同一后端

重点调优参数(server 块内)

listen 3306;
proxy_pass mysql_cluster;
proxy_connect_timeout 10s;   # 建立TCP连接超时,不要太长
proxy_timeout 600s;          # TCP连接空闲超时,MySQL长连接一定要设置
proxy_buffer_size 16k;       # TCP数据缓冲区,四层不需要大buffer

验证命令

# 检查配置语法
nginx -t

# 平滑重载
nginx -s reload

# 验证端口监听
ss -tlnp | grep 3306

生产重要注意事项

  1. 模块检查

nginx -V | grep stream
# 看是否有 --with-stream,没有就要重新编译Nginx
  1. MySQL 集群场景区分

    • MySQL 读写分离:stream LB 一般做读节点负载均衡;写节点单点,不放入这个 upstream

    • MGR 主从集群:可以把多个 MGR 只读节点放入 upstream 做读流量分发

  2. 被动健康检查局限 Nginx 原生 stream 只能探测TCP 连接能不能建立;无法探测 MySQL 实例是否正常(比如 MySQL 进程活着,但实例卡死、只读、复制异常)。

    解决办法:第三方 ngx_stream_upstream_check_module 主动健康检查,可发 MySQL ping 探测,需要打补丁重新编译 Nginx。

  3. 防火墙:Nginx 服务器需要放开 3306 端口;Nginx 机器要能访问后端 MySQL 节点 3306 端口。

  4. 连接池注意 应用侧连接池连接到 Nginx 的 3306,Nginx 再和后端 MySQL 建立独立 TCP 连接;两层连接池,要注意连接数上限,防止连接打满

扩展:Redis TCP 负载均衡示例(stream 块内追加)

upstream redis_cluster {
    least_conn;
    server 10.0.1.20:6379 max_fails=3 fail_timeout=30s;
    server 10.0.1.21:6379 max_fails=3 fail_timeout=30s;
}
server {
    listen 6379;
    proxy_pass redis_cluster;
    proxy_connect_timeout 5s;
    proxy_timeout 300s;
}

本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://www.yijunzhao.cc/archives/nginx-stream-tcp-layer-4-load-balancing-mysql-cluster-config

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/