分片集群比单机更吃ulimit,因其新增mongos和config server角色,导致文件描述符与进程数消耗呈几何增长:mongos需为每个客户端连接(2 fd + 1 thread)及每个分片副本集节点维持长连接池,config server还需处理复制心跳与chunk迁移,并发中等时即易打满默认限制;且/etc/security/limits.conf须按实际运行用户(如mongod、mongos)精确配置,systemd服务还必须显式设置limitnofile/limitnproc,否则仍沿用1024 fd/4096 nproc默认值。

为什么分片集群比单机更吃 ulimit
分片集群不是简单叠加几个 mongod,而是引入了 mongos 和 config server 两层新角色,资源消耗呈几何级增长。每个 mongos 实例不仅要处理客户端连接(2 fd + 1 thread/连接),还要为每个分片副本集的所有节点维持后台连接池——比如 3 分片 × 每个副本集 3 节点 = 9 条长连接,每条至少占 2 个文件描述符。再加上 config server 的复制心跳、均衡器迁移 chunk 的并发读写,ulimit -n 和 ulimit -u 很容易在中等并发下打满。
/etc/security/limits.conf 配置必须指定用户名,不能用 *
CentOS 7 的 systemd 默认忽略 * 通配符,只认具体用户名。如果你用 mongod 用户运行服务,就得明确写:
mongod soft nofile 65535 mongod hard nofile 65535 mongod soft nproc 65535 mongod hard nproc 65535
同理,mongos 若以 mongos 用户启动,也得单独加四行;若混用 root,就改写 root。漏掉任意一个用户,对应进程启动后就会沿用系统默认的 1024 fd / 4096 nproc,后续报 too many open files 或 fork: retry: Resource temporarily unavailable 就不奇怪了。
systemd 服务文件里必须加 LimitNOFILE 才真正生效
/etc/security/limits.conf 只对 login shell 生效,而 systemd 启动的服务绕过了 PAM limits 加载链。所以还必须编辑对应服务文件:
- 查服务名:
systemctl list-units | grep mongo,常见为mongod.service、mongos.service - 执行:
sudo systemctl edit mongos.service - 填入:
[Service] LimitNOFILE=65535 LimitNPROC=65535
然后重载:sudo systemctl daemon-reload && sudo systemctl restart mongos。不加这步,ulimit -n 在 mongos 进程里仍显示 1024。
验证是否生效不能只看 ulimit -a
ulimit -a 显示的是当前 shell 的限制,不是 mongos/mongod 进程的实际值。正确验证方式是:
- 查 mongos 进程号:
pgrep -f "mongos.*port" - 进其 namespace:
cat /proc/<code>PID/limits | grep "Max open files\|Max processes" - 输出应类似:
Max open files 65535 65535 files,而非1024 4096
特别注意:如果看到 65535 但实际仍报错,大概率是 fs.file-max 内核参数太低(需 ≥ 2× 总 fd 上限),或 /etc/security/limits.d/20-nproc.conf 里硬编码了 nproc=4096 覆盖了你的配置——这个文件在 CentOS 7 中优先级更高,必须直接改它。











