Kafka消费者抵消承诺可完成的未来

时间:2017-09-22 16:27:22

标签: java multithreading java-8 apache-kafka kafka-consumer-api

我在一个线程内创建了一个Kafka消费者实例作为构造函数的一部分,并且在run方法内部的线程内我调用不同的Web服务并保持调用非阻塞我正在使用可完成的未来。我的问题是我无法通过调用thenApply方法并传递Kafka使用者实例来发出提交,因为它给了我一个Kafka使用者不是线程安全的错误。虽然在我的提交方法中我已经制作了代码

synchronized(consumer) {
  commitResponse();
}

我仍然得到ConcurrentModificationException

class KafkaConsumerThread implements Runnable {

  KafkaConsumer<String, String> consumer;

  public KafkaConsumerThread(Properties properties) {
    consumer = new KafkaConsumer<String, String>(properties);    
    ...
  }

  @Override
  public void run() {
    try {
      // synchronized (consumer) {
      consumer.subscribe(topics);
      while (true) {
        if (closed.get()) {
          consumer.close();
        }
        ConsumerRecords<String, String> records = consumer.poll(120000);
        for (ConsumerRecord<String, String> record : records) {
          getAsyncClient().prepareGet(webServiceUrl)
              .execute()
              .toCompletableFuture()
              .thenApply(resp -> callAnotherService1(resp))
              .thenApply(resp -> callAnotherService2(resp))
              .thenApply(resp -> commitResponse(resp, consumer));
          }
        }
      }
    } catch (Exception ex) {
      ...
    }

在上面的代码中,我在commitResponse方法中得到了异常,&#34; KafkaConsumer对于多线程访问并不安全&#34;。虽然在我的提交响应中如果我将提交包含在synchronized(消费者)中,我仍然会收到错误。

1 个答案:

答案 0 :(得分:0)

很可能是因为poll方法未同步,并且执行时(仍在运行时持有内部kafka锁),而异步GET执行提交。

请参阅私有方法的引用: org.apache.kafka.clients.consumer.KafkaConsumer.acquire()org.apache.kafka.clients.consumer.KafkaConsumer.release()org.apache.kafka.clients.consumer.KafkaConsumer