Java连接MongoDB副本集时连接池被清空的问题求助
解决MongoDB副本集Java连接触发
MongoConnectionPoolClearedException问题 问题根源
- 容器主机名无法被本地Java环境解析:副本集初始化时使用Docker内部容器名(如
mongo-primary)作为节点地址,Java客户端从MongoDB获取副本集节点列表后,尝试用这些容器名建立连接,但本地系统无法解析该类内部主机名,导致连接失败并触发连接池清空。 - Secondary节点未对外暴露端口:初始部署仅映射了Primary节点的端口,Secondary节点未对外开放端口,即使解析了主机名也无法建立连接。
解决步骤
1. 重新部署MongoDB节点(暴露所有节点端口)
先清理原有容器,再重新启动节点并为每个节点映射独立的本地端口:
# 停止并删除原有容器(若需保留数据可跳过此步) docker stop mongo-primary mongo-secondary1 mongo-secondary2 docker rm mongo-primary mongo-secondary1 mongo-secondary2 # 重新启动节点,映射所有端口到本地 docker run -d --name mongo-primary --net mongo-cluster -p 27017:27017 mongo:4.0 --replSet rs0 docker run -d --name mongo-secondary1 --net mongo-cluster -p 27018:27017 mongo:4.0 --replSet rs0 docker run -d --name mongo-secondary2 --net mongo-cluster -p 27019:27017 mongo:4.0 --replSet rs0
2. 修改副本集配置为外部可访问地址
进入Primary容器的Mongo Shell,重新配置副本集节点地址为本地可访问的localhost:端口:
docker exec -it mongo-primary mongo
在Mongo Shell中执行以下命令:
use admin // 获取当前副本集配置 var rsConfig = rs.conf(); // 修改每个节点的host为本地可访问地址 rsConfig.members[0].host = "localhost:27017"; rsConfig.members[1].host = "localhost:27018"; rsConfig.members[2].host = "localhost:27019"; // 应用新配置 rs.reconfig(rsConfig);
执行rs.status()确认所有节点状态变为PRIMARY或SECONDARY,等待同步完成。
3. 更新Java连接字符串
将连接字符串中的容器名替换为localhost加对应端口:
ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017,localhost:27018,localhost:27019/?replicaSet=rs0");
4. 优化连接配置(可选)
添加心跳频率配置,避免因心跳超时触发连接池异常:
MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(connectionString) .applyToSocketSettings(builder -> builder.connectTimeout(30, TimeUnit.SECONDS)) .applyToClusterSettings(builder -> builder.serverSelectionTimeout(30, TimeUnit.SECONDS) .heartbeatFrequency(10, TimeUnit.SECONDS)) // 调整心跳频率,降低超时概率 .build();
5. 验证驱动版本兼容性
确保MongoDB Java驱动版本与4.0版本服务器兼容,推荐使用3.8.x至4.0.x区间的驱动版本。
验证
运行Java代码,此时应能稳定连接副本集并执行命令,不再触发MongoConnectionPoolClearedException异常。
内容的提问来源于stack exchange,提问作者user23318156
相关产品推荐
相关产品推荐

