有序启动并等待容器

kiu*_*_88 5 junit apache-kafka apache-kafka-connect testcontainers

我在使用 Junit5 的测试中有两个容器@Testcontainers, aKafka和 a KafkaConnect

@Container
private final KafkaContainer kafka = new KafkaContainer()
        .withNetwork(network)
        .withNetworkAliases("kafka");

@Container
private final GenericContainer KafkaConnect = 
        new GenericContainer("confluentinc/cp-kafka-connect:latest")
        .withEnv("CONNECT_BOOTSTRAP_SERVERS", "kafka:9092")
        .withEnv("CONNECT_REST_PORT", 8083)
        .withNetwork(network)
        ...
Run Code Online (Sandbox Code Playgroud)

当我执行测试时,我发现一个错误,因为 Kafka Connect 服务kafkaConnect未正确启动(映射端口 8083 未侦听)。这是因为在执行期间到达 url之前kafkaConnect启动,由于尚未运行,因此未获得响应。然后,我尝试推迟启动以等待确保可用性。kafkakafka:9092kafkaConnectkafkakafkaConnectkafkakafka:9092

我尝试了不同的方法来做到这一点,但我没有解决问题。我尝试添加一些配置。

startupTimeout。据我所知,此配置不会推迟启动操作。它只是增加检查容器是否启动的时间。

.withStartupTimeout(Duration.of(240, SECONDS)) 
Run Code Online (Sandbox Code Playgroud)

我还尝试了一些配置waitingFor,例如基于超时的配置,正如预期的那样,它产生的结果与withStartupTimeout

.waitingFor(Wait.defaultWaitStrategy().withStartupTimeout(...))
Run Code Online (Sandbox Code Playgroud)

或基于端口,这不能解决我的问题,因为它不指向kafka容器,而是指向kafkaConnect.

.waitingFor(Wait.forHttp("http://kafka:9092"))
Run Code Online (Sandbox Code Playgroud)

我还尝试添加多次启动尝试,但它不能解决问题,因为kafkaConnect有时会重新启动,但总是在此之前kafka

作为解决方案,我删除了@Container声明kafkaConnect以便手动管理其生命周期,因此我添加了显式启动到测试用例,请参见下文

@Test
test() {
    kafkaConnect.start();
    ...
}
Run Code Online (Sandbox Code Playgroud)

此确保kafkaConnect在 后开始kafka。但是,我没有找到一种解决方案来在容器定义期间通过策略、策略或类似的方式来定义顺序,以便添加容器之间的依赖关系并避免命令式和手动的生命周期管理。

是否可以?

M. *_*ard 1

import org.junit.rules.RuleChain;

// @Container <-- Remove annotation.
private final KafkaContainer kafka = new KafkaContainer()...;

// @Container <-- Remove annotation.
private final GenericContainer kafkaConnect = 
        new GenericContainer("confluentinc/cp-kafka-connect:latest")
        .withEnv("CONNECT_BOOTSTRAP_SERVERS", "kafka:9092")
        ...;

// Start the containers in the correct order.  Prevents
// "Mapped port can only be obtained after the container is started"
// error.
@Rule
public final RuleChain chain = 
    RuleChain
    // Started first.
    .outerRule(kafka)
    // Started later.
    .around(kafkaConnect);

Run Code Online (Sandbox Code Playgroud)