mongos 本身不支持 maxPoolSize 参数,因其是路由层而非客户端,不维护对外连接池;其入站连接上限由 maxIncomingConnections 与系统 ulimit -n 中较小值决定,且需通过 systemd 正确配置 LimitNOFILE 才生效。

mongos 本身不支持设置 maxPoolSize,这个参数只存在于客户端驱动里;在 mongos 上设连接限制,必须用 maxIncomingConnections + 系统级 ulimit -n 双重生效。
为什么 mongos 没有 maxPoolSize 参数
mongos 是路由层,不是客户端——它不维护“连接池”,而是转发请求、管理到后端 mongod 的连接。所谓“mongos 的连接池”其实是它自己作为客户端连向分片和 config server 的连接,这部分由内部逻辑控制,不可通过 maxPoolSize 配置。所有带 maxPoolSize 的文档或报错,基本都混淆了 mongos 和应用客户端的角色。
常见错误现象:
- 在 mongos 启动参数里加
--maxPoolSize 50,启动失败并报unrecognized option - 在 mongos 的
/etc/mongos.conf里写net.maxPoolSize: 50,配置加载成功但完全不生效 - 应用端明明设了
maxPoolSize: 10,但 mongos 进程的连接数还是飙到上千——说明问题出在服务端限制缺失,而非客户端没控住
mongos 实际可用的最大入站连接数怎么算
mongos 的入站连接上限由两个值共同决定:显式配置的 maxIncomingConnections 和系统级 ulimit -n,取二者中较小者。哪怕你配了 maxIncomingConnections: 10000,只要 ulimit -n 是 4096,mongos 启动时就会默默降级,并在日志里写 maxIncomingConnections reduced to 4096 due to file descriptor limit。
验证当前生效值的方法:
- 查 mongos 进程实际打开的 fd 上限:
cat /proc/$(pgrep mongos)/limits | grep "Max open files" - 查 mongos 启动时解析的配置:
db.runCommand({getCmdLineOpts: 1})→ 看parsed.net.maxIncomingConnections - 确认是否被降级:如果
parsed里写的值比你配置的大,但limits显示的是小值,就是被 ulimit 卡住了
systemd 下改 ulimit 容易漏掉的关键点
绝大多数线上 mongos 是用 systemd 管理的,而 systemd 默认的 LimitNOFILE 是 1024 或 4096,远低于 mongos 默认的 65536。你在 shell 里执行 ulimit -n 65536 对它完全无效。
必须做三件事(缺一不可):
- 编辑
/etc/systemd/system/mongos.service,在[Service]段添加:LimitNOFILE=65536和TasksMax=infinity - 如果用非登录用户(如
mongod用户)运行 mongos,还要同步改/etc/security/limits.conf,加两行:mongod soft nofile 65536和mongod hard nofile 65536 - 执行
sudo systemctl daemon-reload && sudo systemctl restart mongos—— 注意是restart,不是reload,因为 ulimit 只在进程启动时读取
连接泄露真正该盯住的三个地方
连接数持续上涨、重启 mongos 后又快速打满,大概率不是配置没调对,而是连接根本没被释放。重点排查:
- 客户端是否复用
MongoClient实例:Node.js 里每次new MongoClient()都开新池,必须全局单例 - 应用是否漏关连接:比如异常分支没调
client.close(),或用完没 return 出来就抛错中断 - 是否有重试风暴:网络抖动时客户端未设
retryWrites=false或maxIdleTimeMS,导致短时间反复建连
mongos 自身不会“泄露”连接,但它会忠实地把每个未关闭的客户端连接维持住——直到对方超时断开,或系统资源耗尽直接拒连。所以看到 connection refused,先别急着调大数字,先看连接从哪来、为何不走。


















