web-dev-qa-db-ja.com

schema.registry.urlなしでAvroをシリアル化するためのKafkaAvroSerializer

私はKafkaとAvroの初心者です。そのため、プロデューサー/コンシューマーを実行しようとしています。これまでのところ、以下を使用して単純なバイトと文字列を生成および消費できました。 :プロデューサーの構成:

    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("key.serializer", "org.Apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer", "org.Apache.kafka.common.serialization.ByteArraySerializer");

    Schema.Parser parser = new Schema.Parser();
    Schema schema = parser.parse(USER_SCHEMA);
    Injection<GenericRecord, byte[]> recordInjection = GenericAvroCodecs.toBinary(schema);

    KafkaProducer<String, byte[]> producer = new KafkaProducer<>(props);

    for (int i = 0; i < 1000; i++) {
        GenericData.Record avroRecord = new GenericData.Record(schema);
        avroRecord.put("str1", "Str 1-" + i);
        avroRecord.put("str2", "Str 2-" + i);
        avroRecord.put("int1", i);

        byte[] bytes = recordInjection.apply(avroRecord);

        ProducerRecord<String, byte[]> record = new ProducerRecord<>("mytopic", bytes);
        producer.send(record);
        Thread.sleep(250);
    }
    producer.close();
}

これで問題はなくなりました。POJOをシリアル化しようとすると問題が発生します。したがって、Avroに付属のユーティリティを使用してPOJOからAvroSchemaを取得することができました。スキーマをハードコーディングし、次にプロデューサーがKafkaProducerを介して送信するジェネリックレコードを作成しようとしました。

    Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.Apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.Apache.kafka.common.serialization.KafkaAvroSerializer");

Schema.Parser parser = new Schema.Parser();
Schema schema = parser.parse(USER_SCHEMA); // this is the Generated AvroSchema
KafkaProducer<String, byte[]> producer = new KafkaProducer<>(props);

ここが問題です:私がKafkaAvroSerializerを使用した瞬間、次の理由によりプロデューサーが起動しません:欠落している必須パラメーター:schema.registry.url

なぜこれが必要なのかを読んで、プロデューサーが送ってきたものをコンシューマーが解読できるようにします。しかし、スキーマはすでにAvroMessageに埋め込まれていませんか? schema.registry.urlを指定せずに、KafkaProducerをKafkaAvroSerializerと使用する実際の例を共有できれば、本当に素晴らしいでしょう

また、スキーマレジストリのユーティリティに関する洞察/リソースを本当に感謝します。

ありがとう!

12
scissorHands

最初に注意してください:KafkaAvroSerializerはVanilla Apacheでは提供されていませんkafka-Confluent Platformによって提供されます。( https://www.confluent.io/ =)、オープンソースコンポーネントの一部として( http://docs.confluent.io/current/platform.html#confluent-schema-registry

迅速な答え:いいえ、KafkaAvroSerializerを使用する場合、スキーマレジストリが必要になります。ここにいくつかのサンプルを参照してください: http://docs.confluent.io/current/schema-registry/docs/serializer-formatter.html

スキーマレジストリの基本的な考え方は、各トピックはavroスキーマを参照するということです(つまり、互いにコヒーレントなデータのみを送信できます。ただし、スキーマには複数のバージョンを含めることができるため、それぞれのスキーマを識別する必要があります記録)

私たちはあなたが暗示するようなすべてのデータのスキーマを書きたくありません-多くの場合、スキーマはあなたのデータよりも大きいです!それは、読むときに毎回それを解析する時間の無駄であり、リソース(ネットワーク、ディスク、CPU)の無駄です

代わりに、スキーマレジストリインスタンスはバインディングを行いますavro schema <-> int schemaIdとシリアライザは、レジストリから取得(および後で使用するためにキャッシュ)した後、データの前にこのIDのみを書き込みます。

したがって、kafka内では、レコードは[<id> <bytesavro>](および技術的な理由でマジックバイト)、これはわずか5バイトのオーバーヘッドです(スキーマのサイズと比較するため)。また、読み取り時に、コンシューマーはIDに対応するスキーマを見つけ、それに関するデシリアライザーアブロバイトを見つけます。 。あなたはコンフルエントなドキュメントでもっと多くを見つけることができます

すべてのレコードのスキーマを記述したい場合は、他のシリアライザが必要になります(独自のシリアライザを記述すると思いますが、簡単に再利用できます https://github.com/ confluentinc/schema-registry/blob/master/avro-serializer/src/main/Java/io/confluent/kafka/serializers/AbstractKafkaAvroSerializer.Java と読み、スキーマレジストリパーツを削除してスキーマに置き換えます。 )。しかし、avroを使用する場合、私はこれを実際に阻止します-1日後、avroレジストリのようなものを実装してバージョン管理を行う必要があります

19
Treziac

チェックされた答えはすべて正しいですが、スキーマの登録を無効にすることができますであることも言及する必要があります。

単にauto.register.schemasからfalseへ。

0
Fritz Duchardt

いつでも手動でSerialiser<T>Deserialiser<T>(およびKafka St​​reamsの場合はSerde<T>)を実装するように値クラスを作成できます。 Javaクラスは通常Avroファイルから生成されるため、直接編集することはお勧めできませんが、ラッピングは冗長である可能性があります。

もう1つの方法は、Javaクラスの生成に使用されるArvoジェネレーターテンプレートを調整し、それらすべてのインターフェイスの実装を自動的に生成することです。 Avro mavenプラグインとgradleプラグインの両方がカスタムテンプレートをサポートしているため、設定は簡単です。

私は作成しました https://github.com/artemyarulin/avro-kafka-deserializable テンプレートファイルを変更し、ファイル生成に使用できるシンプルなCLIツールを使用します

0
Artem Yarulin