mongos路由延迟高通常源于DNS解析慢、连接池不足、跨区网络RTT高或config server响应慢;应分别通过禁用IPv6 DNS、调优连接参数、同可用区部署及配置config副本集等措施精准排查优化。

mongos 路由延迟高,先看是不是 DNS 解析拖慢了
很多集群里 mongos 启动后首次查询慢、偶发超时,其实不是分片逻辑问题,而是它在解析 shard 地址时卡在 DNS 查询上。默认情况下,mongos 会反复调用系统 getaddrinfo(),而某些 DNS 服务器响应慢或返回 AAAA 记录触发 IPv6 回退,导致单次路由决策多耗 1–3 秒。
实操建议:
- 启动
mongos时加--bind_ip 127.0.0.1并在配置文件中显式写死所有shard的 IP(而非域名),绕过 DNS; - 若必须用域名,确保 DNS 服务器能快速响应
A记录,且禁用AAAA(在/etc/gai.conf中加precedence ::ffff:0:0/96 100); - 用
strace -e trace=getaddrinfo,connect -p $(pgrep mongos)抓一下实际解析行为,确认是否真卡在这步。
mongos 到 shard 的连接复用不足,导致频繁建连
mongos 默认对每个 shard 维护一个连接池,但池大小和超时参数不调优时,高并发下容易打满连接、触发重试或排队,表现为路由层延迟抖动。
实操建议:
- 通过
--maxConnsPerHost 200(或配置文件中net.maxIncomingConnections)提升单 shard 连接上限; - 设置
--minConnsPerHost 10避免冷启动时连接池为空; - 检查
shard端的net.maxIncomingConnections是否足够——若 shard 实例只允许 64 连接,而你配了 200,实际仍会拒绝新连; - 用
db.adminCommand({ "connPoolStats": 1 })在mongos上查当前连接分布,确认是否有 shard 连接数长期占满。
集群内网络拓扑跨可用区或跨机房,RTT 成瓶颈
哪怕 DNS 和连接池都调好了,如果 mongos 和某个 shard 之间 RTT 超过 10ms(比如跨 AZ 或混用公网 IP),一次路由 + 执行的延迟就很难压到 50ms 内。MongoDB 的路由决策本身不重,但每次请求都要走“mongos → shard → mongos”往返,网络是硬约束。
实操建议:
- 用
mtr或ping -c 10 shard-host测各mongos到每个shard的稳定 RTT,超过 5ms 就该警惕; - 把同组
mongos和其主要服务的shard放在同一可用区,避免跨区流量走云厂商内网网关; - 禁用
shard的bindIpAll,改用具体内网 IP 绑定,并在mongos的sharding.config.shards中也填内网地址——防止因路由表误判走公网路径; - 若实在无法收缩网络距离,考虑在应用侧加本地
mongos(每台应用机器起一个),减少远端路由跳数。
config server 响应慢,间接拖累 mongos 路由决策
mongos 每次遇到未知 chunk range 或元数据变更(如 balance、addShard),都会去 config server 查 config.chunks 和 config.shards。如果 config server 是单节点、磁盘慢、或被其他操作阻塞,mongos 就会卡在元数据读取上,表现就是“突然某几秒所有请求变慢”。
实操建议:
- config server 必须是副本集(3 节点),不能是单节点或
mongod --configsvr单实例; - 确保 config server 使用高性能磁盘(如 NVMe),且
storage.journal.enabled: true; - 避免在 config server 上执行非必要操作,例如不要在上面跑
mongodump或手动更新config.*集合; - 用
db.currentOp({ secs_running: { $gt: 2 } })在 config server 上抓长事务,重点看有没有锁住config.chunks的操作。
真正卡住 mongos 路由的,往往不是分片逻辑本身,而是 DNS、连接池、网络路径、config server 这四个环节里的某一个掉链子。逐个验证比盲目调 mongos 参数更有效。特别是 DNS 和跨区网络,最容易被忽略,也最难从日志里直接看出。










