部署在Google Cloud Run的SpringBoot应用无法连接MongoDB集群
错误日志
2024-07-14T01:15:32.428Z INFO 1 --- [localhost:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server localhost:27017 2024-07-14 02:15:32.433 BST com.mongodb.MongoSocketOpenException: Exception opening socket at com.mongodb.internal.connection.SocketStream.lambda$open$0(SocketStream.java:84) ~[mongodb-driver-core-4.11.1.jar!/:na] at java.base/java.util.Optional.orElseThrow(Optional.java:403) ~[na:na] at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:84) ~[mongodb-driver-core-4.11.1.jar!/:na] at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:211) ~[mongodb-driver-core-4.11.1.jar!/:na] at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.lookupServerDescription(DefaultServerMonitor.java:196) ~[mongodb-driver-core-4.11.1.jar!/:na] at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:156) ~[mongodb-driver-core-4.11.1.jar!/:na] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na] Caused by: java.net.ConnectException: Connection refused at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na] at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na] at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:549) ~[na:na] at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597) ~[na:na] at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na] at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na] at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:76) ~[mongodb-driver-core-4.11.1.jar!/:na] at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:104) ~[mongodb-driver-core-4.11.1.jar!/:na] at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:78) ~[mongodb-driver-core-4.11.1.jar!/:na] ... 4 common frames omitted
已完成的排查操作
Cloud Run服务相关
- 本地运行应用可正常连接MongoDB集群及数据库
- 容器端口配置为8080,Dockerfile构建并本地运行SpringBoot容器验证正常
- 已添加MongoDB连接字符串作为环境变量
- 网络配置:通过自定义Serverless VPC Connector连接VPC用于出站流量
- 路由规则:仅将私有IP请求路由至VPC
VPC网络相关
- 基于默认网络创建Serverless VPC访问连接器
- 创建优先级1000的出站防火墙规则,允许27017端口流量
Cloud NAT相关
- 基于默认网络创建公网类型Cloud NAT网关及云路由器(未宣告IP范围或子网),BGN标识符自动配置
- 映射配置:
- 高可用:开启
- 源端点类型:包含VM实例、GKE节点、Serverless
- 源子网及IP范围:所有子网的主、次要IP范围
- 绑定静态IP:xx.xxx.xx.xxx,匹配0.0.0.0/0
MongoDB集群配置
- 已将以下IP加入白名单:
- 集群静态IP地址
- 0.0.0.0/0
- Serverless VPC Connector的CIDR(10.8.0.0/28)
使用的连接字符串
"mongodb+srv://admin:generatedPassword@cluster0.fqwmsk8.mongodb.net/InventoryDB?retryWrites=true&w=majority"
排查建议
检查应用配置是否正确读取环境变量
日志显示应用尝试连接localhost:27017,说明实际生效的连接地址不是配置的集群地址。需确认SpringBoot配置文件(如application.properties/application.yml)中是否正确引用环境变量,例如:spring.data.mongodb.uri=${MONGODB_URI}而非硬编码
mongodb://localhost:27017。同时检查代码中是否存在硬编码的MongoDB地址逻辑。验证环境变量的正确性
检查Cloud Run控制台中环境变量的取值是否正确,注意不要包含多余的引号(例如连接字符串两端的双引号需移除)。可以在Cloud Run服务中添加调试日志,输出实际读取到的MongoDB连接URI,确认是否与预期一致。确认网络路由逻辑
你的路由规则设置为"仅将私有IP请求路由至VPC",而MongoDB Atlas的srv连接属于公网请求,需确认Cloud NAT是否能正确为Serverless流量提供公网出口。可以临时调整路由规则,允许所有出站流量走公网(或通过Cloud NAT),测试是否能连接成功,以此排除路由规则的影响。检查DNS解析能力
MongoDB的srv连接依赖DNS解析获取集群节点地址,需确认Cloud Run环境中是否能正常解析cluster0.fqwmsk8.mongodb.net的SRV记录。可以在容器中添加DNS调试命令(如nslookup -type=SRV cluster0.fqwmsk8.mongodb.net),验证解析结果是否正确。排查Serverless VPC Connector的配置
如果你的MongoDB集群部署在VPC内(而非Atlas公网集群),需确认VPC Connector的CIDR是否与MongoDB所在子网连通,防火墙规则是否双向允许27017端口流量(入站和出站)。若为Atlas公网集群,VPC Connector可能无需启用,直接通过Cloud NAT走公网即可。
内容的提问来源于stack exchange,提问作者nullPtr

