前面我们学习的 HTTP 反向代理、负载均衡都属于七层应用层代理,只能处理 HTTP/HTTPS 协议。而 Nginx 从 1.9.0 版本开始支持 TCP 四层负载均衡,1.9.13 版本新增 UDP 负载均衡能力,常用于 MySQL、Redis、DNS 这类基于 TCP/UDP 的服务集群转发。
依赖模块:
ngx_stream_proxy_module:TCP/UDP 代理转发ngx_stream_upstream_module:后端服务器分组、调度、健康检查 、 编译安装 Nginx 时必须增加编译参数:--with-stream,否则没有 stream 功能 官方文档:https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html
重要区别:
- 七层 http {}:识别 HTTP 请求、Header、URI,只能代理 http 类业务
- 四层 stream {}:写在主配置 main 段,不解析应用层协议,只转发数据包,TCP/UDP 通用
1.1 Stream 模块核心参数说明
stream 块直接写在 nginx.conf 的最外层(和 http {} 平级)
stream {
upstream 后端组名 {
server ip:port [参数];
}
server {
listen 端口 [udp reuseport];
proxy_pass 后端组名;
proxy_connect_timeout; # 和后端建立连接超时
proxy_timeout; # 连接建立后,空闲超时,超时自动断开连接
proxy_responses N; # UDP专用,等待后端返回几个应答包,DNS一般写1
}
}
server 后端节点参数和 http upstream 基本一致:
weight:权重max_fails:连续失败次数,到达后标记节点不可用fail_timeout:节点标记故障后,多久重新探测backup:备份节点hash $remote_addr consistent:一致性哈希,TCP 长连接场景会话绑定
调度算法同样支持:轮询(默认)、weight 权重、least_conn 最少连接、hash 一致性哈希;stream 没有 ip_hash 指令,会话保持用
hash $remote_addr consistent
1.2 实战案例 1:TCP 四层负载均衡 - MySQL 集群代理
MySQL 使用 3306 端口 TCP 协议,适合用 Nginx stream 做四层转发。
环境准备
- Nginx 代理节点:172.25.254.10
- RS3:172.25.254.11,MariaDB,server-id=11
- RS4:172.25.254.12,MariaDB,server-id=12
# RS3、RS4 安装 mariadb
[root@RS3 ~]# dnf install mariadb-server -y
[root@RS4 ~]# dnf install mariadb-server -y
# 修改配置文件设置server-id
[root@RS3 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=11
[root@RS4 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=12
# 启动服务,创建远程登录用户
[root@RS3 ~]# systemctl enable --now mariadb
[root@RS4 ~]# systemctl enable --now mariadb
MariaDB [(none)]> create user dragon@'%' identified by '123';
MariaDB [(none)]> grant all on *.* to dragon@'%';
Nginx 配置
编辑主配置文件 /usr/local/nginx/conf/nginx.conf,stream 和 http {} 同级
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
写入配置内容:
stream {
upstream mysql_server {
server 172.25.254.11:3306 max_fails=3 fail_timeout=30s;
server 172.25.254.12:3306 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.10:3306;
proxy_pass mysql_server;
proxy_connect_timeout 30s;
proxy_timeout 300s;
}
}
http {
# 原有http七层配置保留不变
}
重载配置:
[root@Nginx ~]# nginx -s reload
测试效果
反复连接代理 IP 查询 server_id,轮询分发到两台数据库:
[root@Nginx ~]# mysql -udragon -p123 -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 11 |
+-------------+
[root@Nginx ~]# mysql -udragon -p123 -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 12 |
+-------------+
故障测试:停止 RS3 的 mariadb
[root@RS3 ~]# systemctl disable --now mariadb
再次访问,请求全部自动调度到存活的 RS4:
[root@Nginx ~]# mysql -udragon -p123 -h172.25.254.10 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 12 |
+-------------+
原理:连续探测失败达到 max_fails,Nginx 自动摘除故障节点,等 fail_timeout 时间后再尝试探测恢复。
1.3 实战案例 2:UDP 四层负载均衡 - DNS 服务
DNS 默认使用 UDP 53 端口,Nginx stream 支持 udp 关键字实现 DNS 轮询。
环境准备
RS3、RS4 部署 bind 作为 DNS 后端服务器
# RS3、RS4安装bind
[root@RS3 ~]# dnf install bind -y
[root@RS4 ~]# dnf install bind -y
步骤 1:修改 named 主配置文件
[root@RS4 ~]# vim /etc/named.conf
options {
// listen-on port 53 { 127.0.0.1; };
// listen-on-v6 port 53 { ::1; };
directory "/var/named";
dump-file "/var/named/data/cache_dump.db";
statistics-file "/var/named/data/named_stats.txt";
memstatistics-file "/var/named/data/named_mem_stats.txt";
secroots-file "/var/named/data/named.secroots";
recursing-file "/var/named/data/named.recursing";
// allow-query { localhost; };
dnssec-validation no;
};
步骤 2:配置区域声明文件
[root@RS4 ~]# vim /etc/named.rfc1912.zones
zone "doubledragon.org" IN {
type master;
file "doubledragon.org.zone";
allow-update { none; };
};
步骤 3:复制区域模板,编辑解析记录
[root@RS4 ~]# cd /var/named/
[root@RS4 named]# cp -p named.localhost doubledragon.org.zone
[root@RS4 named]# vim doubledragon.org.zone
zone 文件内容:
$TTL 1D
@ IN SOA dns.doubledragon.org. rname.invalid. (
0 ; serial
1D ; refresh
1H ; retry
1W ; expire
3H ) ; minimum
NS dns.doubledragon.org.
dns A 172.25.254.11
步骤 4:启动 DNS 服务
[root@RS4 ~]# systemctl enable --now named
Nginx UDP 配置
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
stream {
upstream dns_server {
server 172.25.254.11:53 max_fails=3 fail_timeout=30s;
server 172.25.254.12:53 max_fails=3 fail_timeout=30s;
}
server {
listen 172.25.254.10:53 udp;
proxy_pass dns_server;
proxy_timeout 1s;
proxy_responses 1;
error_log logs/dns.log;
}
}
关键点:
udp标记这个监听端口是 UDP 协议proxy_responses 1:DNS 一次请求只返回一个应答包,UDP 场景必加reuseport可选,多进程端口复用,提升 UDP 并发性能
重载 Nginx:
[root@Nginx ~]# nginx -s reload
dig 解析测试
[root@Nginx ~]# dig dns.doubledragon.org @172.25.254.10
;; ANSWER SECTION:
dns.doubledragon.org. 86400 IN A 172.25.254.12
[root@Nginx ~]# dig dns.doubledragon.org @172.25.254.10
;; ANSWER SECTION:
dns.doubledragon.org. 86400 IN A 172.25.254.11
多次 dig,解析结果轮流来自两台 DNS 后端,UDP 负载均衡生效。
七层 vs 四层负载均衡对比总结
| 类型 | 配置块 | 识别协议 | 典型场景 | 优点 |
|---|---|---|---|---|
| 七层负载均衡 | http{} | HTTP/HTTPS | Web 网站、接口、动静分离、缓存 | 可以识别 url、header、cookie,功能丰富 |
| 四层负载均衡 | stream{} | TCP/UDP | MySQL、Redis、DNS、SSH | 只转发数据包,性能更高,通用所有 TCP/UDP 服务 |
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2301_80092853/article/details/168661809



