应根据应用并发量与请求耗时计算:理论连接数≈每秒最大请求数×平均耗时,再加20%缓冲;如200线程、80ms耗时,则maxPoolSize设20即可,避免过高导致资源挤占或过低引发超时。

mongos连接池大小到底该设多少
别直接抄网上的 maxPoolSize=100。生产环境里,这个值必须和你的应用线程数、请求并发模型、以及 mongos 自身的 --maxConns 限制对齐,否则不是连接打满就是资源空转。
关键判断依据就一条:应用端每秒最大并发请求数 × 单次请求平均耗时(秒)≈ 理论所需连接数。比如你 Spring Boot 应用用的是 Tomcat 默认 200 线程池,平均请求耗时 80ms,那理论峰值连接数约是 200 × 0.08 = 16。再加 20% 缓冲,maxPoolSize=20 就够用了——远低于默认的 100。
- 设太高:客户端连接数虚高,挤占 mongos 的文件描述符和内存;同时触发 mongos 层的
--maxConns拒绝(默认 65536,但单机实际受 ulimit 限制) - 设太低:连接等待队列堆积,日志里频繁出现
Timed out after 30000 ms while waiting for a connection - 注意 minPoolSize 不建议设为 0:冷启动时大量新建连接 + SSL 握手,会拖慢首请求响应
Spring Boot 里怎么配 mongos 连接池参数
Spring Boot 2.4+ 使用 MongoClientSettings 替代旧版 MongoProperties,配置必须显式构造,不能靠 application.yml 简单覆盖。
正确做法是在配置类中手动构建 MongoClientSettings:
@Bean
public MongoClient mongoClient() {
ConnectionString connectionString = new ConnectionString("mongodb://mongos1:27017,mongos2:27017/?replicaSet=rs0&connectTimeoutMS=5000&socketTimeoutMS=30000");
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(connectionString)
.applyToClusterSettings(builder -> builder.applyToHosts(list -> list.add(new ServerAddress("mongos1", 27017))))
.applyToSocketSettings(builder -> builder.readTimeout(30, TimeUnit.SECONDS).connectTimeout(5, TimeUnit.SECONDS))
.applyToConnectionPoolSettings(builder ->
builder.maxConnectionPoolSize(20) // ← 核心参数
.minConnectionPoolSize(5)
.maxConnectionLifeTime(0, TimeUnit.MILLISECONDS) // 0 表示不限制
.maxConnectionIdleTime(10, TimeUnit.MINUTES))
.build();
return MongoClients.create(settings);
}
-
maxConnectionPoolSize和minConnectionPoolSize是唯一需要调的两个池大小参数 -
maxConnectionLifeTime设为 0 更稳妥:mongos 进程长期运行,连接没必要强制回收 -
maxConnectionIdleTime建议设为 5–10 分钟:避免空闲连接长期占用 mongos 端口和 fd
为什么连 mongos 还要关心 mongos 自身的 --maxConns
mongos 不是透明代理,它自己也要维护到后端 shard 和 config server 的连接池。如果客户端连接池开太大,而 mongos 启动时没调 --maxConns,就会在内部连接层面先卡住。
典型现象是:客户端报连接超时,但 mongos 日志里查不到对应请求记录,db.currentOp() 也看不到活跃操作——问题其实出在 mongos 接入层被自身限制拦住了。
- mongos 默认
--maxConns是 65536,但 Linux 系统级ulimit -n往往只有 65535 或更低 - 务必在 mongos 启动脚本里显式设置:
mongos --configdb csrs/... --maxConns 60000 - 同时检查
ulimit -n是否 ≥--maxConns + 1000(预留系统开销) - 验证方式:连接 mongos 后执行
db.runCommand({connPoolStats: 1}),看totalCreated和available是否接近上限
连接池监控与异常兜底怎么做
光配数字不监控,等于没配。真正上线后必须能快速回答两个问题:连接是不是真在用?卡在哪一层?
推荐三个最低成本可观测点:
- 客户端侧:用 Micrometer + Prometheus 抓取
MongoClientMetrics中的numberOfAvailableConnections和numberOfCheckedOutConnections,持续低于 1 就说明池子不够 - mongos 侧:定时跑
db.runCommand({connPoolStats: 1}),重点关注hosts下每个 shard 的inUse和available差值 - 系统层:
ss -s | grep "tcp:"看 mongos 进程当前 ESTABLISHED 连接数,是否逼近--maxConns
最后提醒一个容易被忽略的点:Spring Boot 的 @Document 实体如果带了 @Id 字段但没设默认值,某些版本驱动会在连接池初始化阶段偷偷执行一次 getLastError 探活,导致冷启动时多建一批连接——确认所有实体 ID 生成逻辑是轻量且无副作用的。











