nginx可通过stream模块实现数据库四层代理与双机热备,需编译启用--with-stream,配置upstream标记backup节点,并让应用连接代理地址而非直连数据库。

Nginx 本身不直接连接或操作数据库,它不能像应用服务器那样建立 JDBC/ODBC 连接。但在双机热备场景下,Nginx 可以通过 stream 模块 对数据库流量(如 MySQL、PostgreSQL 的 TCP 连接)做四层代理与故障转移,从而实现数据库访问的高可用——即:前端应用只需连一个固定 IP:Port,背后自动路由到两个热备数据库中的健康节点。
✅ 关键前提:启用 Nginx stream 模块
默认编译的 Nginx 不包含 stream 模块,必须显式开启:
./configure --with-stream make && make install
验证是否生效:
/usr/local/nginx/sbin/nginx -V 2>&1 | grep -o with-stream # 输出有 "with-stream" 即表示已支持
⚠️ 若使用 yum/apt 安装的预编译包(如
nginx-full),需确认发行版是否内置 stream 支持;CentOS 7 默认源中 nginx 常不含该模块,建议源码编译。
✅ 配置数据库 TCP 层代理(双机热备)
假设客户侧有两个 MySQL 实例:
- 主库:
192.168.80.140:3306 - 备库:
192.168.80.141:3306(已配置主从同步或集群同步)
目标:让所有应用统一连接 192.168.80.100:3307(Nginx 代理地址),Nginx 自动转发至健康数据库节点。
在 nginx.conf 最外层(不在 http{} 内)添加:
stream {
upstream db_backend {
server 192.168.80.140:3306 max_fails=3 fail_timeout=30s;
server 192.168.80.141:3306 max_fails=3 fail_timeout=30s backup;
}
server {
listen 3307;
proxy_pass db_backend;
proxy_timeout 1h;
proxy_responses 1;
proxy_connect_timeout 5s;
proxy_timeout 30s;
}
}
说明:
-
backup标记使该节点仅在其他节点全部失效时才启用(典型热备模式); -
max_fails和fail_timeout控制健康检查:连续失败 3 次后剔除 30 秒; -
proxy_timeout避免长连接被意外中断; -
proxy_responses 1表示仅转发首个响应包(适用于 MySQL 协议握手阶段)。
? 注意:MySQL 协议是状态化 TCP 流,Nginx stream 不解析 SQL,只做连接级转发。因此要求主备库数据一致,且应用层需支持重连(如连接池配置
autoReconnect=true或failOverReadOnly=false)。
✅ 应用端适配要点
应用不再直连数据库 IP,而是连接 Nginx 代理地址:
| 项目 | 原配置 | 新配置 |
|---|---|---|
| JDBC URL | jdbc:mysql://192.168.80.140:3306/mydb |
jdbc:mysql://192.168.80.100:3307/mydb |
| 连接池参数 | 建议启用重连机制 | 必须设置 socketTimeout=30000、connectTimeout=5000
|
常见错误规避:
- ❌ 不要依赖 Nginx 做读写分离(stream 层无 SQL 解析能力);
- ❌ 不要省略
backup标识——否则两节点都视为 active,可能造成写冲突; - ✅ 建议配合
tcp_check或外部脚本(如mysqladmin ping)做更精准的健康探测(需自定义health_check脚本 +keepalived或nginx-plus)。
✅ 高阶增强:配合 Keepalived 实现 Nginx 自身双机热备
若 Nginx 代理本身也需高可用(防单点),应在两台 Nginx 服务器上部署 Keepalived,共用一个虚拟 IP(如 192.168.80.200),对外暴露该 VIP 作为数据库代理入口:
- 应用连接
192.168.80.200:3307 - Keepalived 管理 VIP 漂移,Nginx 进程健康由
nginx_check.sh脚本守护 - 数据库代理配置完全一致,无需修改
这样就构成完整链路:
应用 → VIP(Keepalived)→ Nginx(stream)→ 热备数据库
不复杂但容易忽略:stream 模块必须启用、backup 要明确标注、应用连接超时需调优。











