KafkaAvroSerializer的额外字节

时间:2019-07-05 15:06:55

标签: serialization apache-kafka avro confluent-schema-registry alpakka

我的设置如下:我正在从ftp服务器中检索xml文件,将它们解组到POJO中,将其映射到Avro生成的类中,然后将其转发到Alpakkas's Producer Sink中,如下所示:

Ftp.ls("/", ftpSettings)
  .filter(FtpFile::isFile)
  .mapAsyncUnordered(10,
    ftpFile -> {
      CompletionStage<ByteString> fetchFile =
        Ftp.fromPath(ftpFile.path(), ftpSettings).runWith(Sink.reduce((a, b) -> a), materializer);
      return fetchFile;
    })
  .map(b -> b.decodeString(Charsets.ISO_8859_1))
  .map(StringReader::new)
  .map(AlpakkaProducerDemo::unmarshalFile)
  .map(AlpakkaProducerDemo::convertToAvroSerializable)
  .map(a -> new ProducerRecord<>(kafkaTopic, a.id().toString(), a))
  .map(record -> ProducerMessage.single(record))
  .runWith(Producer.committableSink(producerSettings, kafkaProducer), materializer);

问题在于,序列化显然无法正常工作。例如。我也想将密钥也进行序列化,尽管它只是一个字符串(要求,不要问)。的配置看起来像:

Map<String, Object> kafkaAvroSerDeConfig = new HashMap<>();
kafkaAvroSerDeConfig.put(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, schemaRegistryUrl);
final KafkaAvroSerializer keyAvroSerializer = new KafkaAvroSerializer();
keyAvroSerializer.configure(kafkaAvroSerDeConfig, true);
final Serializer<Object> keySerializer = keyAvroSerializer;
final Config config = system.settings().config().getConfig("akka.kafka.producer");
final ProducerSettings producerSettings = ProducerSettings.create(config, keySerializer, valueSerializer)
  .withBootstrapServers(kafkaServer);

在Kafka中,这会导致键的内容正确,但在字符串的开头\u0000\u0000\u0000\u0000\u0001N会出现一些(明显)额外的字节。您可以想象,这给价值带来了破坏。我怀疑Avro序列化不能与Alpakka使用的信封API配合使用,因此可能需要事先序列化为byte[]并使用通用的ByteSerializer。但是,那么使用SchemaRegistry毫无意义。

1 个答案:

答案 0 :(得分:1)

前五个字节与序列化格式版本(字节0)和模式注册表中的Avro模式版本(字节1-4)有关:https://docs.confluent.io/current/schema-registry/serializer-formatter.html#wire-format

另一个选择可能只是使用带有FTP源和XML转换的Kafka Connect。