我正在spring-boot中实现一个端点,该端点在被调用时将转储位于kafka主题中的所有消息(用于测试)。
我期望的行为是,当生产者写到“ testTopic”主题,随后消费者进行民意测验时,它应该阅读刚刚产生的消息。
我观察到的行为是使用者无法使用产生的消息。此外,如果生产者产生更多的消息(例如10-15),则消费者将一次性丢弃所有消息。从这一点开始,如果生产者甚至生成一条消息,那么消费者将按预期进行消费。
直觉上,我认为设置FETCH_MIN_BYTES_CONFIG
可能与此有关-也许使用者正在等待写入足够的字节。但这已设置为1字节(默认值),并且不能解释随后成功读取单个消息的过程。
接下来,我想也许我是在创建主题之前就在注册使用者(通过太快地调用注册端点)。但是我从kafka-topics.sh
确认,在注册使用者之前,该主题存在。
我注意到,如果启用了偏移自动提交功能,则该行为有时是预期的,有时不是预期的。手动提交偏移量(在下面的代码中未显示)时,行为非常奇怪,如上所述。
我还知道制作人正在通过使用kafka-console-consumer
进行确认来按预期工作。
还尝试将轮询超时增加到1秒,但是没有运气。
// Consumer
@Component
public class TestConsumer{
private KafkaConsumer testConsumer = null;
public void registerConsumer(final String consumerId) {
if (consumer == null) {
Properties props = new Properties();
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "<some_address>:<some_port>");
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, "testGroup");
testConsumer = new KafkaConsumer<String, String>(props);
testConsumer.subscribe(Collections.singletonList("testTopic"));
}
else{
logger.debug("Consumer already registered");
}
}
public Map<String, List<String>> consume() {
Map<String, List<String>> messages = new HashMap<>();
if (testConsumer == null){
logger.error("testConsumer was not instantiated");
return null;
}
ConsumerRecords<String, String> records = testConsumer.poll(Duration.ofMillis(100));
List<String> buffer = new ArrayList<>();
for (ConsumerRecord<String, String> record: records){
logger.debug(String.format("Consuming %s", record.value()));
buffer.add(record.value());
}
messages.put("data", buffer);
return messages;
}
}
步骤顺序为: 1. Spring Boot应用程序启动 2. kafka主题已创建,我可以通过kafka控制台进行确认 3.我注册生产者和消费者 4.生产者进行生产,我可以使用kafka控制台(不同的消费者组)进行确认 5.消费者无法消费
我希望结果如下:
{
"data" : ["message1"]
}
我得到的是
{
"data" : []
}
有什么主意,为什么消费者直到写了一定数量的消息后才使用记录?
EDIT_1:
向消费者添加了props.setProperty(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
属性,但没有任何效果。
答案 0 :(得分:0)
在您手动调用此testConsumer.poll(Duration.ofMillis(100))
时。您需要不断地从主题中汇集。就像在一个无限的while循环中一样。例如:
while (true) {
Map records = consume();
logger.debug("received records: {}", records);
}
看看这个链接:Kafka consumer