测试代码配置远程Elasticsearch集群却尝试连接localhost:9200问题排查求助
从你的描述和日志来看,核心矛盾点在于:project-elasticsearch模块的测试能正常连接远程ES,但依赖它的project-api模块测试时,先成功连接了远程ES,随后却尝试连接localhost:9200并报错。结合日志中的SingleNodeHostProvider(属于Reactive Elasticsearch客户端组件)和你配置的RestHighLevelClient(同步客户端),我整理了以下几个可能的原因和对应的解决方案:
1. Reactive Elasticsearch客户端未配置,触发默认localhost连接
你的日志中出现的SingleNodeHostException是Reactive Elasticsearch客户端的报错,而你仅配置了同步的RestHighLevelClient。这说明project-api中可能存在以下情况:
- 引入了
spring-boot-starter-data-elasticsearch-reactive或spring-data-elasticsearch-reactive依赖; - 代码中使用了Reactive风格的ES操作类(比如
ReactiveElasticsearchRepository、ReactiveElasticsearchTemplate)。
当Reactive客户端没有被显式配置时,会自动使用默认的localhost:9200地址,这就是报错的根源。
解决方案:
- 如果不需要Reactive客户端:移除
project-api中所有Reactive Elasticsearch相关的依赖,检查build.gradle中是否有类似如下依赖并删除:implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch-reactive' - 如果需要使用Reactive客户端:在你的ES配置类中添加Reactive客户端的配置Bean,和同步客户端保持一致的远程地址:
@Bean public ReactiveElasticsearchClient reactiveElasticsearchClient(ElasticsearchProperty elasticsearchProperty) { ConnectionProperty connProp = elasticsearchProperty.getContents().getConnectionProperty(); String hostAndPort = new HttpHost(connProp.getHosts(), Integer.parseInt(connProp.getPorts())).toHostString(); ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo(hostAndPort) .withBasicAuth(connProp.getUser(), connProp.getPassword()) // 配置账号密码 .withConnectTimeout(Duration.ofMillis(connProp.getConnectionTimeout())) .withSocketTimeout(Duration.ofMillis(connProp.getSocketTimeout())) .build(); return ReactiveRestClients.create(clientConfiguration); }
2. project-api未正确加载远程ES配置文件
project-elasticsearch能正常加载elasticsearch-local.yml,但project-api可能因为配置文件路径、Profile激活问题,没有正确读取到远程ES的配置,导致部分组件(比如Reactive客户端)使用默认值。
解决方案:
- 确认
project-api的测试类上是否指定了配置文件路径,比如添加:@TestPropertySource(locations = "classpath:elasticsearch-local.yml") - 检查
project-api的resources目录下是否存在elasticsearch-local.yml,或者通过Gradle配置确保project-elasticsearch的配置文件被正确引入到project-api的classpath中:// 在project-api的build.gradle中添加 sourceSets { main { resources { srcDirs += project(':project-elasticsearch').sourceSets.main.resources } } test { resources { srcDirs += project(':project-elasticsearch').sourceSets.test.resources } } } - 确认测试环境是否激活了正确的Profile,如果配置文件是基于Profile的,需要在测试类上添加
@ActiveProfiles("local")。
3. 测试上下文的配置覆盖问题
project-api的测试类可能没有正确导入project-elasticsearch中的ES配置类,或者自身定义了冲突的ES配置Bean,导致远程配置被覆盖。
解决方案:
- 在
project-api的测试类上显式导入project-elasticsearch的配置类:@Import(ElasticsearchConfig.class) // 替换成你实际的配置类名 @SpringBootTest public class YourApiTest { // ... } - 检查测试类中是否存在自定义的
@Configuration类,里面是否定义了ES相关的Bean,如果有,删除或修改为使用远程配置。
额外验证点
你可以在project-api的测试中添加一段代码,打印当前加载的ES配置,确认配置是否正确读取:
@Autowired private ElasticsearchProperty elasticsearchProperty; @Test public void printEsConfig() { System.out.println("ES Host: " + elasticsearchProperty.getContents().getConnectionProperty().getHosts()); System.out.println("ES Port: " + elasticsearchProperty.getContents().getConnectionProperty().getPorts()); }
如果打印出来的是远程地址,那基本可以确定是Reactive客户端未配置的问题;如果打印的是默认值,那就是配置文件加载的问题。
内容的提问来源于stack exchange,提问作者nullmari

