我开始让两个消费者使用来自Kafka的消息,有六个分区,因此为每个消费者分配了三个分区。我发现消费者在消费一段时间后无法轮询任何消息,我可以看到滞后存在,这意味着仍然存在已发送的消息。
当我杀死程序并重新启动它时,消费者可以使用剩余的消息,但过了一会儿,它会再次停止,尽管还有其他消息。
没有任何错误消息,我的代码部分如下:
Map<TopicPartition, OffsetAndMetadata> offsets = ...;
consumer.commitAsync(offsets, null);
我在一个JVM中启动了两个线程,每个线程都会自己创建KafkaConsumer。
我使用了AsyncCommit,并且我将回调类设置为null。如:
{{1}}
这是否导致了这个问题?
答案 0 :(得分:0)
将需要查看更多代码,因此很难知道您拥有哪些属性,但是KafkaConsumer
并不是线程安全的;最好是启动应用程序的多个实例,而不是在同一JVM中启动两个线程。
无论如何,您都可以在Confluent的站点上找到Java使用者的可复制示例,即同步提交或异步。
这里的the more-advanced basic example比简单的while(true) { poll(); }
允许您扩展和包装Thread或ExecutorService的地方要多。
public abstract class BasicConsumeLoop<K, V> implements Runnable {
private final KafkaConsumer<K, V> consumer;
private final List<String> topics;
private final AtomicBoolean shutdown;
private final CountDownLatch shutdownLatch;
public BasicConsumeLoop(Properties config, List<String> topics) {
this.consumer = new KafkaConsumer<>(config);
this.topics = topics;
this.shutdown = new AtomicBoolean(false);
this.shutdownLatch = new CountDownLatch(1);
}
public abstract void process(ConsumerRecord<K, V> record);
public void run() {
try {
consumer.subscribe(topics);
while (!shutdown.get()) {
ConsumerRecords<K, V> records = consumer.poll(500);
records.forEach(record -> process(record));
// commit();
}
} finally {
consumer.close();
shutdownLatch.countDown();
}
}
public void shutdown() throws InterruptedException {
shutdown.set(true);
shutdownLatch.await();
}
}