web-dev-qa-db-ja.com

Kafka:カスタムシリアライザーの作成

Kafka 0.8.1。でPOCを構築しようとしています。自分のJavaクラスをKafka一連の文字列データ型を含むメッセージです。デフォルトのシリアライザクラスまたはKafkaライブラリに付属する文字列シリアライザクラスを使用できません。独自のシリアライザを作成してフィードする必要があると思いますプロデューサーのプロパティ。Kafka(Javaの場合)でカスタムシリアライザーの例を書くことに気づいている場合は、共有してください。ありがとうございました。

20
Paaji

カスタムシリアライザーを作成するために必要なものは次のとおりです。

  1. ジェネリックに指定されたオブジェクトを使用してEncoderを実装します
    • VerifiablePropertiesコンストラクタを指定する必要があります
  2. toBytes(...)メソッドをオーバーライドして、バイト配列が返されることを確認します
  3. シリアライザクラスをProducerConfigに挿入します

プロデューサーのカスタムシリアライザーの宣言

質問で述べたように、Kafkaは、プロデューサの特定のシリアライザを宣言する手段を提供します。シリアライザクラスはProducerConfigインスタンスに設定され、そのインスタンスは必要なProducerクラス。

Kafkaのプロデューサーの例 に従う場合、ProducerConfigオブジェクトを介してPropertiesを構築します。プロパティファイルをビルドするときは、必ず以下を含めてください。

props.put("serializer.class", "path.to.your.CustomSerializer");

Kafkaを使用して、メッセージをログに追加する前にメッセージをシリアル化するために使用するクラスへのパスを指定します。

Kafkaが理解するカスタムシリアライザを作成する

Kafkaが適切に解釈できるカスタムシリアライザを作成するには、Encoder[T] scala that that Kafkaが提供するクラスを実装する必要があります。 Javaは奇妙です に特性を実装していますが、次のメソッドは私のプロジェクトでJSONをシリアル化するために機能しました:

public class JsonEncoder implements Encoder<Object> {
    private static final Logger logger = Logger.getLogger(JsonEncoder.class);
    // instantiating ObjectMapper is expensive. In real life, prefer injecting the value.
    private static final ObjectMapper objectMapper = new ObjectMapper();

    public JsonEncoder(VerifiableProperties verifiableProperties) {
        /* This constructor must be present for successful compile. */
    }

    @Override
    public byte[] toBytes(Object object) {
        try {
            return objectMapper.writeValueAsString(object).getBytes();
        } catch (JsonProcessingException e) {
            logger.error(String.format("Json processing failed for object: %s", object.getClass().getName()), e);
        }
        return "".getBytes();
    }
}

あなたの質問は、ログに追加されたすべてのメッセージに対して1つのオブジェクト(CustomMessageと呼ぶことにします)を使用しているように聞こえます。その場合、シリアライザは次のようになります。

package com.project.serializer;

public class CustomMessageEncoder implements Encoder<CustomMessage> {
    public CustomMessageEncoder(VerifiableProperties verifiableProperties) {
        /* This constructor must be present for successful compile. */
    }

    @Override
    public byte[] toBytes(CustomMessage customMessage) {
        return customMessage.toBytes();
    }
}

プロパティ設定は次のようになります。

props.put("serializer.class", "path.to.your.CustomSerializer");
41
Sam Berry

エンコードとデコーダの両方を実装する必要がある

public class JsonEncoder implements Encoder<Object> {
        private static final Logger LOGGER = Logger.getLogger(JsonEncoder.class);

        public JsonEncoder(VerifiableProperties verifiableProperties) {
            /* This constructor must be present for successful compile. */
        }

        @Override
        public byte[] toBytes(Object object) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                return objectMapper.writeValueAsString(object).getBytes();
            } catch (JsonProcessingException e) {
                LOGGER.error(String.format("Json processing failed for object: %s", object.getClass().getName()), e);
            }
            return "".getBytes();
        }
    }

デコーダーコード

public class JsonDecoder  implements Decoder<Object> {
    private static final Logger LOGGER = Logger.getLogger(JsonEncoder.class);
    public JsonDecoder(VerifiableProperties verifiableProperties) {
        /* This constructor must be present for successful compile. */
    }

    @Override
    public Object fromBytes(byte[] bytes) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(bytes, Map.class);
        } catch (IOException e) {
            LOGGER.error(String.format("Json processing failed for object: %s", bytes.toString()), e);
        }
        return null;
    }
}

Pomエントリ

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.1.3</version>
</dependency>

Kafkaプロパティにデフォルトのエンコーダーを設定します

properties.put("serializer.class","kafka.serializer.DefaultEncoder");

ライターとリーダーのコードは次のとおりです

byte[] bytes = encoder.toBytes(map);
        KeyedMessage<String, byte[]> message =new KeyedMessage<String, byte[]>(this.topic, bytes);

JsonDecoder decoder = new JsonDecoder(null);
Map map = (Map) decoder.fromBytes(it.next().message());
12
Harvinder Singh