Spring3.1.x+Testcontainer集成Elasticsearch8时连接被拒绝问题
问题:Spring 3.1 @ServiceConnection 配合Testcontainers Elasticsearch 8.x 连接被拒绝
我用CircleCI有段时间了,最近想升级集成测试,用上Testcontainers和Spring 3.1的新特性,尤其是@ServiceConnection。这个配置在MongoDB上没问题,但升级到Elasticsearch 8.1.x后,一直遇到循环连接被拒绝的问题。
我知道Elasticsearch 8默认开启安全功能,已经通过环境变量禁用了相关配置:
xpack.security.enabled=falsexpack.security.transport.ssl.enabled=falsexpack.security.http.ssl.enabled=false
另外我也清楚Testcontainers的Elasticsearch容器会设置默认密码,但我在application-test.yml里已经配置了用户名、密码和URI:
spring.elasticsearch.username: user spring.elasticsearch.password: changeme spring.elasticsearch.uris: http://localhost:9200
但看起来这些配置没生效——要么是@ServiceConnection注解忽略了它们,要么是容器没绑定到配置的地址。
我的测试类代码如下:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @Testcontainers @ActiveProfiles("test") @Slf4j public class FooControllerIT { @Container @ServiceConnection static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo").withTag("xxx")); @Container @ServiceConnection static ElasticsearchContainer elasticsearchContainer = new ElasticsearchContainer(DockerImageName.parse("docker.elastic.co/elasticsearch/elasticsearch") .withTag("8.x")) .withEnv("xpack.security.enabled", "false") .withEnv("xpack.security.transport.ssl.enabled","false") .withEnv("xpack.security.http.ssl.enabled","false"); @Autowired private SomeController someController; @BeforeEach void setUp() { mongoDBContainer.start(); elasticsearchContainer.start();// 启动时或访问属性时直接失败 <---- Awaitility.await().atMost(Duration.ofMinutes(2)).until(() -> elasticsearchContainer.isRunning()); // <---- 根本执行不到这里,说明不是容器没启动完成的问题 log.info("blabla"+elasticsearchContainer.isRunning()+","+elasticsearchContainer.isHostAccessible()); } }
我推测问题出在:程序试图连接配置里的9200端口,但Testcontainers实际给Elasticsearch容器分配了随机端口。
之前我用ApplicationContextInitializer手动设置属性解决过:
public static class ElasticConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { elasticsearchContainer.start(); await().atMost(120, TimeUnit.SECONDS).until(elasticsearchContainer::isRunning); String hostAddress = "http://" + elasticsearchContainer.getHttpHostAddress(); TestPropertyValues.of( "spring.elasticsearch.uris=" + hostAddress) .applyTo(applicationContext); log.info("finished Elastic config"+ elasticsearchContainer.getBoundPortNumbers()+","+elasticsearchContainer.getLogs()); } }
但我以为Spring 3.1的@ServiceConnection应该能自动处理这些,不需要手动写初始化器了?
错误堆栈信息:
Caused by: java.net.ConnectException: Connection refused: no further information at java.base/sun.nio.ch.Net.pollConnect(Native Method) at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:946) at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvent(DefaultConnectingIOReactor.java:174) at org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor.processEvents(DefaultConnectingIOReactor.java:148) at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor.execute(AbstractMultiworkerIOReactor.java:351) at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.execute(PoolingNHttpClientConnectionManager.java:221) at org.apache.http.impl.nio.client.CloseableHttpAsyncClientBase$1.run(CloseableHttpAsyncClientBase.java:64) at java.base/java.lang.Thread.run(Thread.java:833)
我希望不用手动覆盖配置,让@ServiceConnection正常工作,这可行吗?是不是我漏了什么配置?
内容的提问来源于stack exchange,提问作者Valentin
相关产品推荐
相关产品推荐

