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はどこに行くべきでしょうか?
スキーマIDは実際にはavroメッセージ自体にエンコードされています。 this を見て、エンコーダー/デコーダーの実装方法を確認してください。
一般に、AvroメッセージをKafkaに送信するとどうなりますか。
0x0
バイトであり、メッセージの種類を区別するために使用されます。スキーマIDは4バイトの整数値です。 restは実際にエンコードされたメッセージです。メッセージをデコードしてここに戻すと、次のようになります。
0x0
であることを確認します。キーがAvroでエンコードされている場合、キーは上記の形式になります。価値についても同様です。このように、キーと値はAvro値であり、異なるスキーマを使用する場合があります。
編集してコメント内の質問に答えます:
実際のスキーマはスキーマリポジトリに格納されます(つまり、スキーマリポジトリの全体のポイントは、実際にはスキーマを格納するためです:))。 Avro Object Container Files形式は、上記の形式とは関係ありません。 KafkaAvroEncoder/Decoderはわずかに異なるメッセージ形式を使用します(ただし、実際のメッセージは確実にまったく同じ方法でエンコードされます)。
これらの形式の主な違いは、オブジェクトコンテナファイルには実際のスキーマが含まれ、そのスキーマに対応する複数のメッセージが含まれる可能性があるのに対し、上記の形式ではスキーマIDとそのスキーマに対応する1つのメッセージのみが含まれるという点です。
1つのKafkaメッセージには複数のAvroメッセージが含まれるため、オブジェクトコンテナーファイルでエンコードされたメッセージを渡すことは、おそらくわかりにくいでしょう。または、1つのKafkaメッセージにはAvroメッセージが1つしか含まれていませんが、その場合、各メッセージにスキーマが含まれます。
Avroスキーマは非常に大きくなる可能性があり(私は600 KB以上のスキーマを見たことがあります)、各メッセージでスキーマを実行することは非常にコストと無駄が多いため、スキーマリポジトリが機能します-スキーマは一度だけフェッチされ、ローカルにキャッシュされます他のすべてのルックアップは、高速なマップルックアップです。