web-dev-qa-db-ja.com

Kafka CommitFailedExceptionコンシューマー例外

複数のコンシューマーを作成し(Kafka 0.9 Java API)を使用)、各スレッドを開始した後、次の例外が発生します

Consumer has failed with exception: org.Apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed due to group rebalance
class com.messagehub.consumer.Consumer is shutting down.
org.Apache.kafka.clients.consumer.CommitFailedException: Commit cannot be completed due to group rebalance
at org.Apache.kafka.clients.consumer.internals.ConsumerCoordinator$OffsetCommitResponseHandler.handle(ConsumerCoordinator.Java:546)
at org.Apache.kafka.clients.consumer.internals.ConsumerCoordinator$OffsetCommitResponseHandler.handle(ConsumerCoordinator.Java:487)
at org.Apache.kafka.clients.consumer.internals.AbstractCoordinator$CoordinatorResponseHandler.onSuccess(AbstractCoordinator.Java:681)
at org.Apache.kafka.clients.consumer.internals.AbstractCoordinator$CoordinatorResponseHandler.onSuccess(AbstractCoordinator.Java:654)
at org.Apache.kafka.clients.consumer.internals.RequestFuture$1.onSuccess(RequestFuture.Java:167)
at org.Apache.kafka.clients.consumer.internals.RequestFuture.fireSuccess(RequestFuture.Java:133)
at org.Apache.kafka.clients.consumer.internals.RequestFuture.complete(RequestFuture.Java:107)
at org.Apache.kafka.clients.consumer.internals.ConsumerNetworkClient$RequestFutureCompletionHandler.onComplete(ConsumerNetworkClient.Java:350)
at org.Apache.kafka.clients.NetworkClient.poll(NetworkClient.Java:288)
at org.Apache.kafka.clients.consumer.internals.ConsumerNetworkClient.clientPoll(ConsumerNetworkClient.Java:303)
at org.Apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.Java:197)
at org.Apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.Java:187)
at org.Apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.Java:157)
at org.Apache.kafka.clients.consumer.internals.ConsumerCoordinator.commitOffsetsSync(ConsumerCoordinator.Java:352)
at org.Apache.kafka.clients.consumer.KafkaConsumer.commitSync(KafkaConsumer.Java:936)
at org.Apache.kafka.clients.consumer.KafkaConsumer.commitSync(KafkaConsumer.Java:905)

その後、通常どおりメッセージの消費を開始します。修正するために、この例外の原因を知りたいと思います。

8
Hugo Carmona

次のパラメータも微調整してみてください。

  • heartbeat.interval.ms-これは、Kafka消費者が考慮されると見なされる前に、指定されたミリ秒数待機することを通知します"デッド"
  • max.partition.fetch.bytes-これにより、ポーリング時にコンシューマーが受信するメッセージの量(最大)が制限されます。

ハートビートがタイムアウトする前にコンシューマーがKafka)にコミットしない場合、リバランスが発生することに気付きました。メッセージの処理後にコミットが発生した場合、メッセージの処理時間によってこれらのパラメーターが決まります。 。したがって、メッセージの数を減らし、ハートビート時間を増やすと、リバランスを回避するのに役立ちます。

また、より多くのパーティションを使用することを検討してください。そうすれば、ポーリングあたりのメッセージが少なくても、データを処理するスレッドが多くなります。

私はこの小さなアプリケーションを作成してテストを行いました。それが役に立てば幸い。

https://github.com/ajkret/kafka-sample

[〜#〜]更新[〜#〜]

Kafka 0.10.xは、受信するメッセージの数を制御するための新しいパラメーターを提供するようになりました。-max.poll.records-で返されるレコードの最大数poll()の1回の呼び出し。

[〜#〜]更新[〜#〜]

Kafkaは、キューを一時停止する方法を提供します。キューが一時停止している間、別のスレッドでメッセージを処理して、KafkaConsumer.poll()を呼び出してハートビートを送信できます。次に、処理が完了した後、KafkaConsumer.resume()を呼び出します。このようにして、ハートビートを送信しないことによる原因のリバランスの問題を軽減します。これがあなたができることの概要です:

while(true) {
    ConsumerRecords records = consumer.poll(Integer.MAX_VALUE);
    consumer.commitSync();

    consumer.pause();
    for(ConsumerRecord record: records) {

        Future<Boolean> future = workers.submit(() -> {
            // Process
            return true;
        }); 


       while (true) {
            try {
                if (future.get(1, TimeUnit.SECONDS) != null) {
                    break;
                }
            } catch (Java.util.concurrent.TimeoutException e) {
                getConsumer().poll(0);
            }
        }
    }

    consumer.resume();
}
11
ajkret