Spring WebFlux嵌入式MongoDB启动失败:测试正常但应用无法启动
我之前也碰到过一模一样的问题——测试跑起来完全没问题,但应用启动时就卡在嵌入式Mongo的连接上,报MongoSocketOpenException。给你几个我亲测有效的排查和解决方向:
首先确保嵌入式Mongo的依赖没被误放到test范围里!很多人一开始为了写测试加依赖,顺手标了test,结果应用启动时根本加载不到这个依赖,自然连不上。
Maven示例(要放在<dependencies>下,不是<dependencyManagement>或<testDependencies>):
<dependency> <groupId>de.flapdoodle.embed</groupId> <artifactId>de.flapdoodle.embed.mongo</artifactId> <version>2.2.0</version> <!-- 和你的mongodb-driver-core 3.6.3兼容 --> </dependency>
另外要注意版本兼容性:你用的是mongodb-driver-core 3.6.3,对应的嵌入式Mongo版本选2.x系列就好,别用最新的3.x,容易出现版本不兼容导致启动失败。
嵌入式Mongo默认用27017端口,如果你的本地已经跑了一个Mongo实例,或者其他程序占用了这个端口,直接就启动失败了。
解决办法很简单,改个端口就行,在application.yml里配置:
spring: data: mongodb: host: localhost port: 27018 embedded: mongodb: port: 27018
如果还是不行,可以加个启动超时配置,给嵌入式Mongo足够的启动时间:
spring: embedded: mongodb: timeout: 30000 # 30秒超时
WebFlux是异步非阻塞的,有时候应用会在嵌入式Mongo完全启动好之前就尝试建立连接,导致连接失败。
可以加个监听类,确保Mongo启动完成后再继续初始化:
@Component public class MongoReadyChecker implements ApplicationListener<ContextRefreshedEvent> { @Autowired private MongoClient mongoClient; @Override public void onApplicationEvent(ContextRefreshedEvent event) { try { // 阻塞等待Mongo连接可用 mongoClient.listDatabaseNames().first().block(Duration.ofSeconds(10)); } catch (Exception e) { throw new IllegalStateException("Embedded MongoDB failed to initialize properly", e); } } }
这个类会在Spring上下文刷新后,主动验证Mongo连接,确保它已经准备好。
- Linux系统:嵌入式Mongo需要把二进制文件解压到临时目录(比如
/tmp),如果应用运行用户没有读写权限,就会启动失败。可以手动指定一个有读写权限的目录:spring: embedded: mongodb: storage: db-dir: ./app-mongo-data - Windows系统:杀毒软件可能会拦截嵌入式Mongo的进程,暂时关闭杀毒软件测试一下,如果能启动,就把嵌入式Mongo的二进制文件加入白名单。
如果以上方法都不行,开启Debug日志看看嵌入式Mongo的启动过程,肯定能找到问题:
logging: level: de.flapdoodle.embed.mongo: DEBUG org.springframework.data.mongodb.core: DEBUG
日志里会显示Mongo的启动命令、端口、是否解压成功这些细节,定位问题会容易很多。
内容的提问来源于stack exchange,提问作者Lorelorelore

