Morphia客户端连接MongoDB,设连接池为1仍多连接,如何解决?
问题描述
测试Morphia客户端连接MongoDB时,已将连接池的minSize和maxSize均设置为1,但客户端仍创建多个连接,需要找到正确限制连接数为1的配置方法。
相关代码
public static void main(String[] args) { ConnectionPoolSettings connectionPoolSettings = ConnectionPoolSettings.builder().minSize(1).maxSize(1).build(); MongoClient client = MongoClients.create( MongoClientSettings .builder() .applyConnectionString(new ConnectionString("mongodb://localhost:27017/test")) .applyToConnectionPoolSettings(builder -> builder.applySettings(connectionPoolSettings)) .build()); MongoDatabase database = client.getDatabase("admin"); Document serverStatus = database.runCommand(new Document("serverStatus", 1)); new Thread(() -> { while(true) { Map connections = (Map) serverStatus.get("connections"); System.out.println("Number of connections " + connections.get("current")); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } } }).start(); try { while(true) TimeUnit.SECONDS.sleep(60); } catch (InterruptedException e) { throw new RuntimeException(e); } }
netstat命令输出
raaghu@FVFH8ET1Q05D ~ % netstat -anv | awk '$5 ~ "27017" {print}'| grep ESTABLISHED tcp4 0 0 127.0.0.1.57851 127.0.0.1.27017 ESTABLISHED 337773 146988 27252 0 00002 00000008 000000000008ef3a 00000080 00000800 1 0 000001 tcp4 0 0 127.0.0.1.57850 127.0.0.1.27017 ESTABLISHED 407373 146988 27252 0 00002 00000008 000000000008ef21 00000080 00000800 1 0 000001 tcp4 0 0 127.0.0.1.57849 127.0.0.1.27017 ESTABLISHED 407373 146988 27252 0 00002 00000008 000000000008ef20 00000080 00000800 1 0 000001
解决方案
1. 先修复连接数监控的代码问题
你当前只在程序启动时获取了一次serverStatus文档,后续循环打印的都是旧数据,根本无法反映实时连接数。要把获取服务器状态的逻辑放到循环里:
new Thread(() -> { while(true) { Document serverStatus = database.runCommand(new Document("serverStatus", 1)); Map connections = (Map) serverStatus.get("connections"); System.out.println("Number of connections " + connections.get("current")); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } } }).start();
2. 优化连接池配置方式
你用applySettings覆盖连接池配置的方式容易出现参数覆盖不全的问题,建议直接在applyToConnectionPoolSettings中直接设置参数,同时补充空闲连接超时配置,避免闲置连接被误创建:
MongoClient client = MongoClients.create(MongoClientSettings .builder() .applyConnectionString(new ConnectionString("mongodb://localhost:27017/test")) .applyToConnectionPoolSettings(poolBuilder -> { poolBuilder.minSize(1); poolBuilder.maxSize(1); // 设置空闲连接超时,避免闲置连接占用资源 poolBuilder.maxConnectionIdleTime(60, TimeUnit.SECONDS); // 设置连接生命周期,强制替换旧连接 poolBuilder.maxConnectionLifeTime(300, TimeUnit.SECONDS); }) .build());
3. 关闭驱动的内部监控连接
MongoDB Java驱动默认会创建独立的监控连接用于采集服务器状态,这部分连接不计入连接池的maxSize限制。如果要彻底把总连接数限制为1,需要关闭这个监控功能:
MongoClient client = MongoClients.create(MongoClientSettings .builder() .applyConnectionString(new ConnectionString("mongodb://localhost:27017/test")) .applyToConnectionPoolSettings(poolBuilder -> { poolBuilder.minSize(1); poolBuilder.maxSize(1); }) // 关闭服务器监控连接 .applyToClusterSettings(clusterBuilder -> { clusterBuilder.serverMonitorListener((ServerMonitorListener) null); }) .build());
4. 确认Morphia的使用规范
如果是通过Morphia的Datastore操作数据库,必须确保复用同一个MongoClient实例——每个MongoClient都会维护自己独立的连接池,多实例会直接导致连接数翻倍。
修改完成后重新运行程序,再用netstat查看连接状态,就能看到只有1个ESTABLISHED状态的连接了。
内容的提问来源于stack exchange,提问作者Raaghu
相关产品推荐
相关产品推荐

