web-dev-qa-db-ja.com

Apache Kafka AvroおよびSchema Repoを使用-メッセージのどこにスキーマIDが表示されますか?

Avroを使用して自分のKafkaメッセージのデータをシリアル化し、それをAvroスキーマリポジトリで使用したいので、すべてのメッセージにスキーマを含める必要はありません。

KafkaでAvroを使用することは人気のあることのように思われ、多くのブログ/スタックオーバーフローの質問/ユーザーグループなどがメッセージとともにスキーマIDを送信することを参照していますが、実際の場所の例を見つけることができません行く必要があります。

Kafkaメッセージヘッダーのどこかにあるはずですが、明確な場所が見つかりません。それがAvroメッセージにある場合は、スキーマに対してデコードしてメッセージの内容を取得し、明らかに問題がある、デコードする必要のあるスキーマを明らかにします。

私はC#クライアントを使用していますが、任意の言語の例がいいでしょう。メッセージクラスには次のフィールドがあります。

public MessageMetadata Meta { get; set; }
public byte MagicNumber { get; set; }
public byte Attribute { get; set; }
public byte[] Key { get; set; }
public byte[] Value { get; set; }

しかし、これらのどれも正しくないようです。 MessageMetaDataには、OffsetとPartitionIdしかありません。

では、AvroスキーマIDはどこに行くべきでしょうか?

20
jheppinstall

スキーマIDは実際にはavroメッセージ自体にエンコードされています。 this を見て、エンコーダー/デコーダーの実装方法を確認してください。

一般に、AvroメッセージをKafkaに送信するとどうなりますか。

  1. エンコーダーは、エンコードするオブジェクトからスキーマを取得します。
  2. エンコーダーは、スキーマレジストリにこのスキーマのIDを要求します。スキーマがすでに登録されている場合は、既存のIDを取得します。そうでない場合は、レジストリがスキーマを登録し、新しいIDを返します。
  3. オブジェクトは次のようにエンコードされます:[マジックバイト] [スキーマID] [実際のメッセージ]ここで、マジックバイトは0x0バイトであり、メッセージの種類を区別するために使用されます。スキーマIDは4バイトの整数値です。 restは実際にエンコードされたメッセージです。

メッセージをデコードしてここに戻すと、次のようになります。

  1. デコーダは最初のバイトを読み取り、それが0x0であることを確認します。
  2. デコーダーは次の4バイトを読み取り、それらを整数値に変換します。これは、スキーマIDがデコードされる方法です。
  3. デコーダがスキーマIDを持っている場合、スキーマレジストリにこのIDの実際のスキーマを要求する場合があります。出来上がり!

キーがAvroでエンコードされている場合、キーは上記の形式になります。価値についても同様です。このように、キーと値はAvro値であり、異なるスキーマを使用する場合があります。

編集してコメント内の質問に答えます:

実際のスキーマはスキーマリポジトリに格納されます(つまり、スキーマリポジトリの全体のポイントは、実際にはスキーマを格納するためです:))。 Avro Object Container Files形式は、上記の形式とは関係ありません。 KafkaAvroEncoder/Decoderはわずかに異なるメッセージ形式を使用します(ただし、実際のメッセージは確実にまったく同じ方法でエンコードされます)。

これらの形式の主な違いは、オブジェクトコンテナファイルには実際のスキーマが含まれ、そのスキーマに対応する複数のメッセージが含まれる可能性があるのに対し、上記の形式ではスキーマIDとそのスキーマに対応する1つのメッセージのみが含まれるという点です。

1つのKafkaメッセージには複数のAvroメッセージが含まれるため、オブジェクトコンテナーファイルでエンコードされたメッセージを渡すことは、おそらくわかりにくいでしょう。または、1つのKafkaメッセージにはAvroメッセージが1つしか含まれていませんが、その場合、各メッセージにスキーマが含まれます。

Avroスキーマは非常に大きくなる可能性があり(私は600 KB以上のスキーマを見たことがあります)、各メッセージでスキーマを実行することは非常にコストと無駄が多いため、スキーマリポジトリが機能します-スキーマは一度だけフェッチされ、ローカルにキャッシュされます他のすべてのルックアップは、高速なマップルックアップです。

26
serejja