Spring Kafka,使用嵌入式Kafka进行测试
我们通过Servicetest和嵌入式卡夫卡观察到一种奇怪的行为 该测试是一个Spock测试,我们使用JUnit规则KafkameBedded并传播BrokerSassString,如下所示:Spring Kafka,使用嵌入式Kafka进行测试,spring,spring-boot,apache-kafka,spring-kafka,Spring,Spring Boot,Apache Kafka,Spring Kafka,我们通过Servicetest和嵌入式卡夫卡观察到一种奇怪的行为 该测试是一个Spock测试,我们使用JUnit规则KafkameBedded并传播BrokerSassString,如下所示: @ClassRule @Shared KafkaEmbedded embeddedKafka = new KafkaEmbedded(1) @Autowired KafkaListenerEndpointRegistry endpointRegistry def setupSpec() { S
@ClassRule
@Shared
KafkaEmbedded embeddedKafka = new KafkaEmbedded(1)
@Autowired
KafkaListenerEndpointRegistry endpointRegistry
def setupSpec() {
System.setProperty("kafka.bootstrapServers", embeddedKafka.getBrokersAsString())
}
通过检查KafkameBedded的代码,使用KafkameBedded(int count)
构造一个实例将导致一个Kafka服务器,每个主题有两个分区
为了解决测试中的分区分配和服务器客户端同步问题,我们遵循SpringKafka的ContainerTestUtils类中的策略
public static void waitForAssignment(KafkaMessageListenerContainer<String, String> container, int partitions)
throws Exception {
log.info(
"Waiting for " + container.getContainerProperties().getTopics() + " to connect to " + partitions + " " +
"partitions.")
int n = 0;
int count = 0;
while (n++ < 600 && count < partitions) {
count = 0;
container.getAssignedPartitions().each {
TopicPartition it ->
log.info(it.topic() + ":" + it.partition() + "; ")
}
if (container.getAssignedPartitions() != null) {
count = container.getAssignedPartitions().size();
}
if (count < partitions) {
Thread.sleep(100);
}
}
}
请注意[…]指示省略的行
我们将metadata.max.age.ms
设置为3000毫秒
因此,它尝试频繁刷新元数据信息
现在让我们困惑的是,如果我们等待两个分区连接,等待就会超时。只有当我们等待一个分区连接时,经过一段时间后,一切都会成功运行
我们是否理解错了代码,在嵌入式Kafka中每个主题有两个分区?只有一个被分配给我们的听众是正常的吗?我无法解释你所看到的片状;是的,默认情况下每个主题有2个分区。我刚刚运行了一个框架容器测试,看到了这个
09:24:06.139 INFO [testSlow3-kafka-consumer-1][org.springframework.kafka.listener.KafkaMessageListenerContainer] partitions revoked:[]
09:24:06.611 INFO [testSlow3-kafka-consumer-1][org.springframework.kafka.listener.KafkaMessageListenerContainer] partitions assigned:[testTopic3-1, testTopic3-0]
我无法解释你看到的片状;是的,默认情况下每个主题有2个分区。我刚刚运行了一个框架容器测试,看到了这个
09:24:06.139 INFO [testSlow3-kafka-consumer-1][org.springframework.kafka.listener.KafkaMessageListenerContainer] partitions revoked:[]
09:24:06.611 INFO [testSlow3-kafka-consumer-1][org.springframework.kafka.listener.KafkaMessageListenerContainer] partitions assigned:[testTopic3-1, testTopic3-0]
对于测试,重要的是设置
spring.kafka.consumer.auto offset reset=earlime
,以避免竞争条件(消费者对生产者的顺序或时间),请参阅
从版本2.5开始,ConsumerOps方法将ConsumerConfig.AUTO\u OFFSET\u RESET\u CONFIG设置为最早。这是因为,在大多数情况下,您希望使用者使用在测试用例中发送的任何消息。ConsumerConfig默认值是最新的,这意味着在使用者开始之前,测试已经发送的消息将不会收到这些记录。要恢复到以前的行为,请在调用方法后将属性设置为latest
对于测试,重要的是设置
spring.kafka.consumer.auto offset reset=earlime
,以避免竞争条件(消费者对生产者的顺序或时间),请参阅
从版本2.5开始,ConsumerOps方法将ConsumerConfig.AUTO\u OFFSET\u RESET\u CONFIG设置为最早。这是因为,在大多数情况下,您希望使用者使用在测试用例中发送的任何消息。ConsumerConfig默认值是最新的,这意味着在使用者开始之前,测试已经发送的消息将不会收到这些记录。要恢复到以前的行为,请在调用方法后将属性设置为latest
我们最初看到的不稳定是关于时间安排和将话题分配给消费者。基本上是()所解决的问题。关于我发现的分区,是什么让我困惑。预先创建主题时,在before()方法中使用构造函数中配置的分区数。当隐式创建主题时,分区数的默认值似乎是1。对我来说,这是同一个问题。当@EmbeddedKafka注释中未声明主题时,将仅自动创建一个分区,该分区由代理属性
num.partitions
控制,默认为1。在最近的SpringKafka测试版本中,您可以在嵌入式代理上设置属性。我们最初看到的不稳定之处是关于时间和向消费者分配主题。基本上是()所解决的问题。关于我发现的分区,是什么让我困惑。预先创建主题时,在before()方法中使用构造函数中配置的分区数。当隐式创建主题时,分区数的默认值似乎是1。对我来说,这是同一个问题。当@EmbeddedKafka注释中未声明主题时,将仅自动创建一个分区,该分区由代理属性num.partitions
控制,默认为1。在最近的spring kafka测试版本中,您可以在嵌入式代理上设置属性。当我们有多个消费者加入到测试中的同一组中时,当发生再平衡时,测试将失败(但不总是在10%左右),这似乎与这里的日志一致。我注意到使用spring嵌入式kafka库时出现了类似的问题。当我们有多个消费者加入到测试中的同一组中时,当发生再平衡时,测试将失败(但不总是在10%左右),这似乎与这里的日志一致。