15 MB以上の大きなメッセージをKafkaで送信するにはどうすればよいですか?


118

文字列メッセージをJava Producer APIを使用してKafka V. 0.8に送信します。メッセージサイズが約15 MBの場合、を取得しMessageSizeTooLargeExceptionます。message.max.bytes40 MB に設定しようとしましたが、それでも例外が発生します。小さなメッセージは問題なく機能しました。

(例外はプロデューサーに表示されます。このアプリケーションにはコンシューマーがありません。)

この例外を取り除くにはどうすればよいですか?

私のサンプルプロデューサー設定

private ProducerConfig kafkaConfig() {
    Properties props = new Properties();
    props.put("metadata.broker.list", BROKERS);
    props.put("serializer.class", "kafka.serializer.StringEncoder");
    props.put("request.required.acks", "1");
    props.put("message.max.bytes", "" + 1024 * 1024 * 40);
    return new ProducerConfig(props);
}

エラーログ:

4709 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with correlation id 214 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
4869 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with    correlation id 217 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5035 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with   correlation id 220 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5198 [main] WARN  kafka.producer.async.DefaultEventHandler  - Produce request with correlation id 223 failed due to [datasift,0]: kafka.common.MessageSizeTooLargeException
5305 [main] ERROR kafka.producer.async.DefaultEventHandler  - Failed to send requests for topics datasift with correlation ids in [213,224]

kafka.common.FailedToSendMessageException: Failed to send messages after 3 tries.
at kafka.producer.async.DefaultEventHandler.handle(Unknown Source)
at kafka.producer.Producer.send(Unknown Source)
at kafka.javaapi.producer.Producer.send(Unknown Source)

5
私の最初の本能は、この巨大なメッセージをいくつかの小さなメッセージに分割するように依頼することです:-/私の推測では、これは何らかの理由で不可能であると考えられますが、それでも再検討する必要があります:巨大なメッセージは通常、設計上の欠陥があることを意味しますどこかで本当に修正する必要があります。
アーロンディグラ2014年

1
おかげで、それは私のロジックをはるかに複雑にするでしょう。15MB前後のメッセージにKafkaを使用するのが悪いのはなぜですか?1 MBは、使用できる最大メッセージサイズの制限ですか?メッセージサイズの制限については、Kafkaのドキュメントではあまりわかりませんでした。
Sonson123 2014年

2
これは、Kafkaやその他のメッセージ処理システムとはまったく関係ありません。私の推論:15 MBファイルに問題が発生した場合、後で混乱を解消するのは非常にコストがかかります。そのため、通常は大きなファイルを多くの小さなジョブに分割します(通常は、同時に実行することもできます)。
アーロンディグラ2014年

圧縮を使用しましたか?もう少し詳細を教えてください。1つの単語から何かを推測するのはちょっと難しい
user2720864

回答:


181

3つ(または4つ)のプロパティを調整する必要があります。

  • コンシューマー側:fetch.message.max.bytes-これは、コンシューマーがフェッチできるメッセージの最大サイズを決定します。
  • ブローカー側:replica.fetch.max.bytes-これにより、ブローカー内のレプリカがクラスター内でメッセージを送信し、メッセージが正しく複製されることを確認できます。これが小さすぎる場合、メッセージは複製されないため、メッセージはコミット(完全に複製)されないため、コンシューマーにはメッセージが表示されません。
  • ブローカー側:message.max.bytes-これは、ブローカーがプロデューサーから受信できるメッセージの最大サイズです。
  • ブローカー側(トピックごと):max.message.bytes-これは、ブローカーがトピックに追加できるメッセージの最大サイズです。このサイズは圧縮前に検証されています。(デフォルトはブローカーのものmessage.max.bytesです。)

私は2番について難しい方法を見つけました。Kafkaから例外、メッセージ、または警告がまったく表示されないので、大きなメッセージを送信する場合はこれを考慮してください。


3
OK、あなたとuser2720864は正しかった。私はmessage.max.bytesソースコードで設定しただけでした。しかし、私はこれらの値をKafkaサーバーの構成で設定する必要がありますconfig/server.properties。今も大きなメッセージが機能します:)。
Sonson123 2014

3
これらの値を高く設定しすぎる既知の欠点はありますか?
Ivan Balashov、2014

7
はい。コンシューマー側では、各fetch.message.max.bytesパーティションにメモリを割り当てます。これは、fetch.message.max.bytes多数のパーティションと組み合わせて膨大な数を使用すると、大量のメモリを消費することを意味します。実際、ブローカー間のレプリケーションプロセスも特殊なコンシューマーであるため、ブローカーのメモリも消費します。
laughing_man

3
ブローカーよりも低くなる可能性があるトピックごとmax.message.bytes構成もあることに注意してください。message.max.bytes
Peter Davis

1
公式ドキュメントによると、コンシューマ側のパラメータとブローカー間のレプリケーションに関するパラメータは/.*fetch.*bytes/ハードリミットではないようです。「これは絶対最大値ではありません。この値よりも大きい場合、レコードバッチはそれでも、確実に進歩を遂げることができるように戻されます。」
Bluu

56

Kafka 0.10新しい消費者に必要なマイナーな変更は、laughing_manの回答と比較して次のとおりです。

  • ブローカー:変更はありません。プロパティmessage.max.bytesとを増やす必要がありreplica.fetch.max.bytesます。message.max.bytesと等しいか、それよりも小さい(*)必要がありreplica.fetch.max.bytesます。
  • プロデューサー:max.request.sizeより大きなメッセージを送信するために増やします。
  • 消費者:max.partition.fetch.bytesより大きなメッセージを受信するために増やします。

(*)message.max.bytes<=の詳細については、コメントをお読みくださいreplica.fetch.max.bytes


2
なぜmessage.max.bytesより小さくする必要があるか知っていますreplica.fetch.max.bytesか?
Kostas 2017年

2
" replica.fetch.max.bytes(デフォルト:1MB)–ブローカーが複製できるデータの最大サイズ。これはmessage.max.bytesより大きくなければなりません。そうでない場合、ブローカーはメッセージを受け入れ、それらの複製に失敗します。潜在的なデータ損失。」出典:Handling-large-messages-kafka
Sascha Vetter

2
リンクをお送りいただきありがとうございます。これは、Clouderaガイドが示唆していることも反映しているようです。ただし、どちらも間違っています。厳密にに大きくする必要がある理由について 、技術的な理由が何もないことに注意してください。今日、コンフルエントの従業員が私が疑っていたことを確認しました。実際には、2つの量は同じである可能性があります。replica.fetch.max.bytesmessage.max.bytes
Kostas 2017年

2
message.max.bytes<replica.fetch.max.bytesまたはmessage.max.bytes=replica.fetch.max.bytes@Kostas に関する更新はありますか?
Sascha Vetter 2017

2
はい、同じにすることができます:mail-archive.com/users@kafka.apache.org/msg25494.html(IsmaelはConfluentで動作します)
Kostas

13

次のプロパティをオーバーライドする必要があります。

ブローカー構成($ KAFKA_HOME / config / server.properties)

  • replica.fetch.max.bytes
  • message.max.bytes

コンシューマー構成($ KAFKA_HOME / config / consumer.properties) このステップは私にはうまくいき
ませんでした。私はそれをコンシューマーアプリに追加し、それはうまくいきました

  • fetch.message.max.bytes

サーバーを再起動します。

詳細については、このドキュメントを参照してください:http : //kafka.apache.org/08/configuration.html


1
コマンドラインコンシューマーの場合、-fetch-size = <bytes>フラグを使用する必要があります。consumer.propertiesファイル(kafka 0.8.1)を読み取っていないようです。また、compression.codecオプションを使用してプロデューサー側から圧縮をオンにすることをお勧めします。
Ziggy Eunicien 2014年

Ziggyのコメントは私のために機能しましたkafka 0.8.1.1。ありがとうございました!
ジェームズ

ConsumerConfigでfetch.message.max.bytesがmax.partition.fetch.bytesに置き換えられている可能性がありますか?
s_bei

12

アイデアは、同じサイズのメッセージがKafka ProducerからKafka Brokerに送信され、次にKafka Consumerによって受信されることです。

カフカプロデューサー->カフカブローカー->カフカコンシューマー

要件が15MBのメッセージを送信することである場合、3つすべてのプロデューサーブローカー、およびコンシューマーを同期させる必要があるとします。

Kafka Producerは 15 MBを送信します-> Kafka Brokerは 15 MBを許可/保存します-> Kafka Consumerは15 MBを受信します

したがって、設定は次のようになります。

a)ブローカーで:

message.max.bytes=15728640 
replica.fetch.max.bytes=15728640

b)消費者:

fetch.message.max.bytes=15728640

2
ConsumerConfigでfetch.message.max.bytesがmax.partition.fetch.bytesに置き換えられている可能性がありますか?
s_bei

7

message.max.bytes属性が消費者のプロパティと同期している必要があることを覚えておくべき重要なことの1つfetch.message.max.bytes。フェッチサイズは、少なくとも最大メッセージサイズと同じ大きさである必要があります。そうしないと、プロデューサーがコンシューマーが消費/フェッチできるよりも大きなメッセージを送信できる場合があります。それを見てみる価値があるかもしれません。
使用しているKafkaのバージョンは?また、取得しているトレースの詳細もいくつか提供します。payload size of xxxx larger than 1000000ログに出てくるようなものはありますか?


1
質問の詳細を更新しました:Kafkaバージョン2.8.0-0.8.0; 今はプロデューサーだけが必要です。
Sonson123 2014年

6

@laughing_manからの回答は非常に正確です。それでも、Qoraからカフカの専門家であるStephane Maarekから学んだ推奨事項を伝えたかったのです。

Kafkaは、大きなメッセージを処理するためのものではありません。

APIはクラウドストレージ(元AWS S3)を使用し、S3の参照をKafkaまたはメッセージブローカーにプッシュするだけです。データを永続化する場所を見つける必要があります。ネットワークドライブである場合もあれば、何でもかまいませんが、メッセージブローカーではありません。

ここで、上記のソリューションを使いたくない場合

メッセージの最大サイズは1MB(ブローカーの設定はと呼ばれますmessage.max.bytesApache Kafkaです。本当にそれがひどく必要な場合は、そのサイズを増やして、プロデューサーとコンシューマーのネットワークバッファーを確実に増やすことができます。

メッセージを分割することに本当に関心がある場合は、各メッセージ分割がまったく同じキーを持ち、同じパーティションにプッシュされるようにします。また、コンシューマーがメッセージを完全に再構築できるように、メッセージコンテンツが「パーツID」を報告する必要があります。 。

メッセージがテキストベース(gzip、snappy、lz4圧縮)であり、データサイズは小さくなるかもしれませんが、魔法ではない場合は、圧縮を検討することもできます。

この場合も、外部システムを使用してデータを保存し、外部参照をKafkaにプッシュする必要があります。これは非常に一般的なアーキテクチャであり、一緒に使用する必要があり、広く受け入れられています。

Kafkaが最も効果的に機能するのは、メッセージが大量でサイズが大きくない場合のみです。

出典:https : //www.quora.com/How-do-I-send-Large-messages-80-MB-in-Kafka


4
「あなたの」推奨事項は、quora.com / How
Mikeに

Kafkaは大きなメッセージを処理しますが、問題はありません。Kafkaホームページの紹介ページでは、ストレージシステムとしても参照しています。
calloc_org

3

landoop kafkaを使用している場合:次のように環境変数で構成値を渡すことができます。

docker run -d --rm -p 2181:2181 -p 3030:3030 -p 8081-8083:8081-8083  -p 9581-9585:9581-9585 -p 9092:9092
 -e KAFKA_TOPIC_MAX_MESSAGE_BYTES=15728640 -e KAFKA_REPLICA_FETCH_MAX_BYTES=15728640  landoop/fast-data-dev:latest `

そして、あなたがrdkafkaを使用している場合は、次のようにプロデューサー構成でmessage.max.bytesを渡します。

  const producer = new Kafka.Producer({
        'metadata.broker.list': 'localhost:9092',
        'message.max.bytes': '15728640',
        'dr_cb': true
    });

同様に、消費者にとって、

  const kafkaConf = {
   "group.id": "librd-test",
   "fetch.message.max.bytes":"15728640",
   ... .. }                                                                                                                                                                                                                                                      
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.