我有一个在 Atlas 上运行的 mongodb 实例和一个在 GAE 上运行的 Spring Boot 应用程序,试图访问该数据库。我在本地运行它没有问题,但在 GAE 上运行时我在日志中看到此错误。
com.mongodb.MongoConfigurationException: Unable to look up SRV record for host xyz-abc-delta-james.gcp.mongodb.net
这是我的 mongodb spring boot 配置
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.field-naming-strategy=org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy
spring.data.mongodb.uri=mongodb+srv://<user>:<password>@xyz-abc-delta-james.gcp.mongodb.net/test?retryWrites=true
我尝试在 GAE 文档中查找某些内容,但没有发现此类错误的痕迹。
Failed to instantiate [com.mongodb.MongoClient]: Factory method 'mongo' threw exception; nested exception is com.mongodb.MongoConfigurationException: Unable to look up SRV record for host xyz-abc-delta-james.gcp.mongodb.net
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:780)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:333)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:172)
at org.eclipse.jetty.plus.annotation.ContainerInitializer.callStartup(ContainerInitializer.java:140)
at org.eclipse.jetty.annotations.ServletContainerInitializersStarter.doStart(ServletContainerInitializersStarter.java:63)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:330)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1406)
at com.google.apphosting.runtime.jetty9.AppEngineWebAppContext.startWebapp(AppEngineWebAppContext.java:159)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1368)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:778)
at org.eclipse.jetty.servlet.ServletContextHandler.doStart(ServletContextHandler.java:262)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:522)
at com.google.apphosting.runtime.jetty9.AppEngineWebAppContext.doStart(AppEngineWebAppContext.java:116)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at com.google.apphosting.runtime.jetty9.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:244)
at com.google.apphosting.runtime.jetty9.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:182)
at com.google.apphosting.runtime.jetty9.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:109)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchServletRequest(JavaRuntime.java:692)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.dispatchRequest(JavaRuntime.java:654)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:624)
at com.google.apphosting.runtime.JavaRuntime$NullSandboxRequestRunnable.run(JavaRuntime.java:818)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:274)
at java.lang.Thread.run(Thread.java:745)
有人遇到过这样的事情吗?这可能是GAE的网络限制吗?
谢谢!
NB:我已经在 serverfault 上发布了此内容,但没有得到任何回复。
显然GAE不支持mogodb uri的最新(3.6x及更高版本)格式,在我切换到相当长的旧版(3.4x及更高版本)uri表示后,一切都顺利进行。
spring.data.mongodb.uri=mongodb://<user>:<password>@xyz-abc-delta-james.gcp.mongodb.net:27017,foo-bar-shard-00-01-tlxzf.gcp.mongodb.net:27017,foo-bar-shard-00-02-tlxzf.gcp.mongodb.net:27017/test?ssl=true&replicaSet=foo-bar-shard-0&authSource=admin&retryWrites=true
由于 Spring boot 对 3.6x 版本有内部依赖,因此我必须手动为 3.4 版本添加 mongodb 依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<exclusions>
<exclusion>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.3</version>
</dependency>
我的问题是我不允许来自我的应用程序的外部流量通过我公开的端口。因此,应用程序对 mongo 集群(或任何其他外部服务)的请求被我的 VPS 防火墙阻止。
我的服务配置有以下片段:
- protocol: TCP
port: 5000
targetPort: 3000
nodePort: 30100
由于我在 ubuntu 风格的 VPS 中运行单节点集群,因此为了允许应用程序通过其端口传出和传入流量,我所要做的就是像这样配置 ufw:
sudo ufw allow 30100
我的应用程序能够使用 mongo+svr 格式和旧格式连接到外部 mongo 集群。