不能直接用 Nginx 对 MongoDB 分片集群做四层负载均衡,因为 mongos 依赖有状态的 Wire Protocol,Nginx stream 无法维持事务、会话、读偏好等上下文;正确做法是用 Nginx 对多个 mongos 实例做带连接粘性的四层负载均衡。

不能直接用 Nginx 对 MongoDB 分片集群做四层负载均衡。
原因:MongoDB 分片集群不支持标准四层代理
MongoDB 分片集群(Sharded Cluster)由 mongos 路由进程、config servers 和 shard replica sets 组成。客户端必须连接 mongos 实例,由它完成查询路由、结果聚合、事务协调等逻辑。mongos 与客户端之间使用 MongoDB Wire Protocol(基于 TCP 的二进制协议),该协议包含会话状态、上下文信息(如读偏好、事务 ID、会话 ID、分片键感知等),不是无状态的简单请求/响应模型。
Nginx 的 stream 模块(四层代理)仅做 TCP/UDP 流转发,不解析 MongoDB 协议,无法识别或维持 mongos 所需的连接上下文。直接代理会导致:
- 事务失败(Transaction context 丢失)
- 会话超时或 session ID 冲突
- 读偏好(readPreference)失效,可能跨 shard 读取不一致数据
- 分片键路由错误,查询被发往错误的 shard
- 连接复用异常,导致 mongos 端连接池混乱
正确架构:Nginx 仅用于 mongos 层的高可用接入
Nginx 可以且应该用于对多个 mongos 实例 做四层负载均衡 —— 因为 mongos 本身是无状态的路由服务(每个 mongos 连接全部 config server 和 shards,独立完成路由)。只要确保客户端始终连接到某一个 mongos(或通过 Nginx 保持连接粘性),整个分片逻辑就完整可靠。
典型部署方式:
- 部署 3–5 个 mongos 实例(建议每台应用服务器就近部署,或集中部署在专用节点)
- 用 Nginx stream 模块反向代理这些 mongos 的 27017 端口
- 启用
hash $remote_addr consistent;或ip_hash;保证客户端 IP 到固定 mongos 的连接粘性(避免跨 mongos 的会话中断) - 配置健康检查(stream 模块需搭配
ngx_http_upstream_check_module补丁或使用 OpenResty + Lua 自检)
Nginx stream 配置示例(带基础健康检查)
注意:官方 Nginx 不内置 TCP 健康检查,以下基于 nginx_upstream_check_module 编译后的版本:
stream {
upstream mongos_backend {
# 启用主动健康检查
check interval=3 rise=2 fall=3 timeout=1;
server 192.168.1.10:27017;
server 192.168.1.11:27017;
server 192.168.1.12:27017;
}
<pre class="brush:php;toolbar:false;"># 使用一致性哈希,减少客户端重连导致的 mongos 切换
upstream mongos_sticky {
hash $remote_addr consistent;
server 192.168.1.10:27017;
server 192.168.1.11:27017;
server 192.168.1.12:27017;
}
server {
listen 27018;
proxy_pass mongos_sticky;
proxy_timeout 60s;
proxy_responses 1;
}}
客户端连接 nginx-host:27018,流量即被稳定分发至后端 mongos,并自动剔除宕机节点。
替代方案与增强建议
若需更高可靠性或动态服务发现,可考虑:
-
DNS 轮询 + 客户端重试:将多个 mongos 注册为同一个 DNS 名(如
mongos.example.com),驱动自动尝试列表中的地址(推荐 MongoDB 官方驱动默认行为) - Consul + Envoy:利用服务网格实现自动注册、健康探测、熔断和连接池管理,更适合云原生环境
- Keepalived + VIP:在 mongos 节点上部署 Keepalived,提供浮动 VIP,轻量且零代理开销
- 永远不要把 Nginx 放在 config server 或 shard primary 前面 —— 它们需要严格的一致性通信,不接受外部四层干扰
核心原则:Nginx 是 mongos 的负载入口,不是 MongoDB 集群的“网关”。分片逻辑必须由 mongos 完整承载,不可绕过或拆解。











