消费者无法从Kafka轮询消息

时间:2018-02-21 23:30:38

标签: java apache-kafka

我开始让两个消费者使用来自Kafka的消息,有六个分区,因此为每个消费者分配了三个分区。我发现消费者在消费一段时间后无法轮询任何消息,我可以看到滞后存在,这意味着仍然存在已发送的消息。

当我杀死程序并重新启动它时,消费者可以使用剩余的消息,但过了一会儿,它会再次停止,尽管还有其他消息。

没有任何错误消息,我的代码部分如下:

Map<TopicPartition, OffsetAndMetadata> offsets = ...;
consumer.commitAsync(offsets, null);

我在一个JVM中启动了两个线程,每个线程都会自己创建KafkaConsumer。

我使用了AsyncCommit,并且我将回调类设置为null。如:

{{1}}

这是否导致了这个问题?

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();
  }
}