SpringBoot连接Mongo Atlas集群遇MongoSocket/UnknownHost异常求助
环境信息
- Java 11
- SpringBoot 2.5.5
- MongoDB 6+
已在MongoDB Atlas中开放所有IP地址访问权限,但连接时抛出如下异常:
Timed out after 30000 ms while waiting to connect. Client view of cluster state is
{type=UNKNOWN, servers=[{address=CusterName:27017, type=UNKNOWN, state=CONNECTING,
exception={com.mongodb.MongoSocketException: CusterName}, caused by {java.net.UnknownHostException: CusterName}}];
nested exception is com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect.
Client view of cluster state is {type=UNKNOWN, servers=[{address=CusterName:27017, type=UNKNOWN, state=CONNECTING,
exception={com.mongodb.MongoSocketException: CusterName}, caused by {java.net.UnknownHostException: CusterName}}]
连接池配置代码
import com.mongodb.*; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.connection.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @Configuration public class MongoConnectionPool { @Bean @Autowired public MongoDatabaseFactory mongoFactory() { List<ServerAddress> serverAddresses = new ArrayList<>(); String address = "<clusterName>:<port>"; String[] hostAndPort = address.split(":"); String host = hostAndPort[0]; Integer port = Integer.parseInt(hostAndPort[1]); ServerAddress serverAddress = new ServerAddress(host, port); serverAddresses.add(serverAddress); ConnectionString connUrl = new ConnectionString("mongodb+srv://<username>:<password>@<clusterName>/<databaseName>"); ConnectionPoolSettings poolSettings = ConnectionPoolSettings.builder() .maxWaitTime(100, TimeUnit.MILLISECONDS) .maxConnectionIdleTime(50, TimeUnit.MILLISECONDS) .maxConnectionLifeTime(30, TimeUnit.MILLISECONDS) .maxSize(12) .minSize(2) .build(); ServerSettings serverSettings = ServerSettings.builder() .heartbeatFrequency(300, TimeUnit.MILLISECONDS) .minHeartbeatFrequency(100, TimeUnit.MILLISECONDS) .build(); ClusterSettings clusterSettings = ClusterSettings.builder() .hosts(serverAddresses) .localThreshold(200, TimeUnit.MILLISECONDS) .serverSelectionTimeout(250, TimeUnit.MILLISECONDS) .requiredClusterType(ClusterType.REPLICA_SET) .mode(ClusterConnectionMode.SINGLE) .requiredReplicaSetName("rs0") .build(); SocketSettings socketSettings = SocketSettings.builder() .connectTimeout(100, TimeUnit.MILLISECONDS) .readTimeout(50, TimeUnit.MILLISECONDS) .build(); SslSettings sslSettings = SslSettings.builder() .enabled(false) .invalidHostNameAllowed(false) .build(); MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(connUrl) .applyToClusterSettings(builder -> builder.applySettings(clusterSettings)) .applyToConnectionPoolSettings(builder -> builder.applySettings(poolSettings)) .applyToServerSettings(builder -> builder.applySettings(serverSettings)) .applyToSocketSettings(builder -> builder.applySettings(socketSettings)) .applyToSslSettings(builder -> builder.applySettings(sslSettings)) .readPreference(ReadPreference.primary()) .build(); MongoClient mongoClient = MongoClients.create(settings); return new SimpleMongoClientDatabaseFactory(mongoClient, "<databaseName>"); } @Bean MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } }
排查思路与解决建议
1. 核心问题:主机名解析失败
异常中的UnknownHostException是关键,说明客户端无法识别集群的主机地址:
- 替换代码中
<clusterName>为Mongo Atlas提供的完整集群域名(例如cluster0.mongodb.net),不能仅填写自定义集群名称; - 在应用服务器上执行
nslookup <集群完整域名>,验证DNS能否正常解析出IP,若失败检查服务器DNS配置或网络连通性。
2. 配置冲突:手动集群设置覆盖自动发现逻辑
代码同时使用了ConnectionString(mongodb+srv协议)和手动构建的ClusterSettings,导致冲突:
mongodb+srv协议会自动解析集群节点、副本集信息,手动指定hosts、ClusterConnectionMode.SINGLE会覆盖该逻辑;- 删除所有
ServerAddress、ClusterSettings相关代码,让驱动通过srv协议自动完成集群发现。
3. SSL配置错误:Atlas强制要求SSL连接
代码中设置sslSettings.enabled(false)违反Atlas的连接规则:
- 将SSL配置改为
enabled(true),或直接删除手动的SslSettings配置(mongodb+srv协议默认启用SSL)。
4. 超时参数设置不合理
代码中超时参数过短(如连接超时100ms),极易触发超时:
- 调整为合理值:
connectTimeout改为3000ms(3秒)serverSelectionTimeout改为10000ms(10秒)maxWaitTime改为5000ms(5秒)
- 连接池的
maxConnectionIdleTime、maxConnectionLifeTime建议设置为分钟级别(如30分钟、1小时),毫秒级别会导致连接频繁销毁重建。
5. 依赖兼容性检查
SpringBoot 2.5.5对应Spring Data MongoDB 3.2.x,需确保Mongo Java驱动与MongoDB 6.x兼容:
- 检查依赖文件中
mongodb-driver-sync版本,建议使用4.4.x及以上(SpringBoot 2.5.5默认4.3.x也可兼容,升级更稳定)。
简化后的配置示例
@Configuration public class MongoConnectionPool { @Bean public MongoDatabaseFactory mongoFactory() { ConnectionString connUrl = new ConnectionString("mongodb+srv://<username>:<password>@<集群完整域名>/<databaseName>?retryWrites=true&w=majority"); ConnectionPoolSettings poolSettings = ConnectionPoolSettings.builder() .maxWaitTime(5, TimeUnit.SECONDS) .maxConnectionIdleTime(30, TimeUnit.MINUTES) .maxConnectionLifeTime(1, TimeUnit.HOURS) .maxSize(12) .minSize(2) .build(); MongoClientSettings settings = MongoClientSettings.builder() .applyConnectionString(connUrl) .applyToConnectionPoolSettings(builder -> builder.applySettings(poolSettings)) .readPreference(ReadPreference.primary()) .build(); MongoClient mongoClient = MongoClients.create(settings); return new SimpleMongoClientDatabaseFactory(mongoClient, "<databaseName>"); } @Bean MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } }
内容的提问来源于stack exchange,提问作者Atul

