MongoDB官方驱动天然支持多mongos自动故障转移,连接字符串用英文逗号分隔地址,参数统一置于末尾;驱动启动时并发探测并选择首个响应成功的mongos,异常时自动切换;需避免DNS轮询、防火墙拦截心跳包等常见陷阱。

多个 mongos 地址写在连接字符串里,MongoDB 官方驱动天然支持自动故障转移,不需要额外配置负载均衡器或代理。
连接字符串里怎么写多个 mongos 地址
标准格式是用英文逗号分隔,所有地址共用一个端口(除非混用),协议和路径部分只写一次:
mongodb://mongos1:27017,mongos2:27017,mongos3:27017/mydb?replicaSet=shard01
注意:replicaSet 参数不是必须的(mongos 本身不构成 replica set),但某些旧版驱动或特定场景下加了更稳;真正关键的是去掉 /?ssl=true 这类单点参数后缀——它不能只挂在最后一个地址上,得统一放在末尾。
- 错误写法:
mongodb://mongos1:27017,mongos2:27017/?ssl=true(?ssl=true只作用于mongos2) - 正确写法:
mongodb://mongos1:27017,mongos2:27017/?ssl=true&connectTimeoutMS=5000 - 如果端口不一致,必须显式写出:
mongodb://mongos1:27017,mongos2:27018,mongos3:27019/
驱动实际怎么选 mongos、什么时候切换
客户端启动时会并发探测所有地址,挑第一个响应成功的建立初始连接;后续请求默认复用该连接,但一旦发生网络中断、mongos 进程退出或返回 NotMasterNoSlaveOk 类错误,驱动会在后台自动尝试列表中下一个可用地址。
- 触发重试的典型错误:
NetworkTimeoutError、ServerSelectionTimeoutError、ConnectionClosedError - 不会因慢查询或业务超时触发切换——那是应用层逻辑,驱动只管连接级存活
- Python PyMongo 默认 30 秒重试间隔,Java Mongo Java Driver 默认 10 秒,可通过
serverSelectionTimeoutMS调整
常见掉坑点:DNS、防火墙和健康检查假象
看起来连得上,其实只是 TCP 握手成功,不代表 mongos 能转发请求。真实故障场景中,最容易被忽略的是:
- DNS 轮询或负载均衡器把多个
mongos映射到同一个 IP,导致“多个地址”实际指向同一台机器 - 防火墙放行了 TCP 连接,但拦截了心跳包(
isMaster命令),驱动误判为节点存活 - 运维手动停掉
mongos后没清空 DNS 缓存,应用仍尝试连已下线地址,拖慢整体发现速度 -
maxPoolSize设太小(如 1),故障转移时新连接建不起来,直接报Timeout waiting for connection
真正要验证是否生效,别只 ping 或 telnet,得用驱动发一条真实命令(比如 db.runCommand({ping:1}))并人为 kill 掉当前活跃的 mongos 进程,看日志里有没有 Topology description changed 这类提示。










