如何从Apache Beam KafkaIO中的kafka主题推断avro模式

时间:2020-06-23 22:53:24

标签: google-bigquery apache-beam confluent-schema-registry apache-beam-io apache-beam-kafkaio

我正在使用Apache Beam的kafkaIO来读取Confluent模式注册表中具有avro模式的主题。 我可以反序列化消息并写入文件。但最终我想写BigQuery。我的管道无法推断模式。 如何提取/推断模式并将其附加到管道中的数据,以便我的下游进程(写入BigQuery)可以推断模式?

这是我在其中使用架构注册表URL设置反序列化器以及从卡夫卡读取的代码:

    consumerConfig.put(
                        AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, 
                        options.getSchemaRegistryUrl());

String schemaUrl = options.getSchemaRegistryUrl().get();
String subj = options.getSubject().get();

ConfluentSchemaRegistryDeserializerProvider<GenericRecord> valDeserializerProvider =
            ConfluentSchemaRegistryDeserializerProvider.of(schemaUrl, subj);

pipeline
        .apply("Read from Kafka",
                KafkaIO
                        .<byte[], GenericRecord>read()
                        .withBootstrapServers(options.getKafkaBrokers().get())
                        .withTopics(Utils.getListFromString(options.getKafkaTopics()))
                        .withConsumerConfigUpdates(consumerConfig)
                        .withValueDeserializer(valDeserializerProvider)
                        .withKeyDeserializer(ByteArrayDeserializer.class)

                        .commitOffsetsInFinalize()
                        .withoutMetadata()

        );

最初,我认为这足以使Beam推断出架构,但是因为hasSchema()返回false,所以这还不够。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

ongoing work支持在KafkaIO中存储在Confluent Schema Registry中的Avro模式的推断。不过,现在也可以在用户管道代码中进行操作。

答案 1 :(得分:0)

此代码可能会起作用,但我尚未测试。

// Fetch Avro schema from CSR
SchemaRegistryClient registryClient = new CachedSchemaRegistryClient("schema_registry_url", 10);
SchemaMetadata latestSchemaMetadata = registryClient.getLatestSchemaMetadata("schema_name");
Schema avroSchema = new Schema.Parser().parse(latestSchemaMetadata.getSchema());

PipelineOptions options = PipelineOptionsFactory.create();
Pipeline p = Pipeline.create(options);


// Create KafkaIO.Read with Avro schema deserializer
KafkaIO.Read<String, GenericRecord> read = KafkaIO.<String, GenericRecord>read()
    .withBootstrapServers("host:port")
    .withTopic("topic_name")
    .withConsumerConfigUpdates(ImmutableMap.of("schema.registry.url", schemaRegistryUrl))
    .withKeyDeserializer(StringDeserializer.class)
    .withValueDeserializerAndCoder((Class) KafkaAvroDeserializer.class, AvroCoder.of(avroSchema));

// Apply Kafka.Read and set Beam schema based on Avro Schema
p.apply(read)
 .apply(Values.<GenericRecord>create()).setSchema(schema,
    AvroUtils.getToRowFunction(GenericRecord.class, avroSchema),
    AvroUtils.getFromRowFunction(GenericRecord.class))

然后我认为您可以将BigQueryIO.WriteuseBeamSchema()一起使用。