【问题标题】:Processing Complex Avro messages using Kafka Streams使用 Kafka Streams 处理复杂的 Avro 消息
【发布时间】:2019-01-21 09:36:57
【问题描述】:

我正在研究 Kafka Streams 上的 POC,我正在使用 Kafka Streams 处理 avro 消息。问题是我的 Avro 消息混合了简单和复杂的类型,所以我发现处理它很困难。

我的 Avro 架构如下所示。

{"type":"record",
"namespace": "com.test",
"name": "backoffice",
"fields": [ {"name": "accountid","type": "string"},
{"name":"amendmentpositionid","type": "int"},
{"name":"booking","type":
{"type":"array","items":
{"namespace":"com.saxo",
"name":"bookingfields",
"type":"record",
"fields":
[{"name":"accountid","type":"string"},{"name":"clientid","type":"int"},
{"name":"clientname","type":"string"},{"name":"exerciseid","type":"int"},
{"name":"hedgeid","type":"int"},{"name":"originatingpositionid","type":"int"},
{"name":"positionid","type":"int"},{"name":"relatedpositionid","type":"int"} ]}}}]}

输入数据如下所述

{"accountid":"1234","amendmentpositionid":1234,"booking":[{"accountid":"898","clientid":333,"clientname":"Non ","exerciseid":2,"hedgeid":100

在将其存储到数据库之前,我需要将其展平并如下所述。

1234,1234,898,333,NON,2,100

为了实现这一点,我尝试使用 Kafka Streams flatmapvalues 操作,但不知何故,我无法在最终输出中保留 id 和 date。

我的 kafka Streams 应用程序如下所示。

package com.test.office.KafkaStreams;

import io.confluent.kafka.serializers.AbstractKafkaAvroSerDeConfig;
import io.confluent.kafka.serializers.KafkaAvroSerializerConfig;
import io.confluent.kafka.streams.serdes.avro.GenericAvroSerde;
import org.apache.avro.generic.GenericData;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.StreamsConfig;
//import io.confluent.kafka;
//import org.apache.kafka.common.serialization.Serdes.
//import io.confluent.kafka.serialiszers.AbstractKafkaAvroSerDeConfig;
import io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.KStreamBuilder;
import com.saxo.backoffice;
import io.confluent.kafka.streams.serdes.avro.GenericAvroSerde;
import org.apache.kafka.streams.kstream.KeyValueMapper;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

public class KafkaAvroSchemaRegistry {


    public static void main(String[] args) {

        Properties properties = new Properties();
        properties.put(StreamsConfig.APPLICATION_ID_CONFIG, "Kafka Avro Topic 8");
        properties.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "server1");
        properties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        properties.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
        properties.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, SpecificAvroSerde.class);
        properties.put(AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG, "http://server2:8081");

        KStreamBuilder builder = new KStreamBuilder();
        KStream<String, testSpecific> testspecific1 = builder.stream("topic10");

        KStream<String,testspecific> output1 = testspecific1.peek((key,value) -> System.out.println(key + value.toString()));


output1.print();
KStream<String,String> test = testspecific1.flatMapValues(value -> value.Booking());

test.print()
        KafkaStreams streams = new KafkaStreams(builder, properties);

        streams.cleanUp();
        streams.start();


        // print the topology
       // System.out.println(streams.toString());

        // shutdown hook to correctly close the streams application
        Runtime.getRuntime().addShutdownHook(new Thread(streams::close));
    }
}

有人能指出正确的方向吗?

【问题讨论】:

    标签: java apache-kafka avro apache-kafka-streams


    【解决方案1】:

    不知何故,我无法在最终输出中保留 id 和日期。

    因为您只是映射到getMessage()。

    尝试获取所有字段

    flatMapValues(value -> 
        String.format("%d,%s,%s", value.getId(), value.getDate(), value.getMessage());
    

    【讨论】:

    • 感谢您的回复。如果我有下面提到的架构怎么办。 "fields": [ {"name": "accountid","type": "string"}, {"name":"amendmentpositionid","type": "int"}, {"name":"booking", “类型”:{“类型”:“数组”,“项目”:{“命名空间”:“com.saxo”,“名称”:“预订字段”,“类型”:“记录”,“字段”:[{ "name":"accountid","type":"string"},{"name":"clientid","type":"int"}, {"name":"clientname","type":"string "},{"name":"exerciseid","type":"int"}, {"name":"hedgeid","type":"int"},{"name":"originatingpositionid","type ":"int"}, {"name":"relatedpositionid","type":"int"} ]}}}]} }
    • 怎么样?如果你想要 CSV,那么你需要为每个字段调用每个 getter
    • 我试过这样。 KStream test1 = backofficetopic1.flatMapValues(value -> String.format("%d,%s", value.getAmendmentpositionid(),value.getAccountid()); 但这不起作用。
    • 那行不通怎么办? value.getAccountId() 在该架构中不存在
    • 感谢您的回答。我已经尝试使用下面提到的 flatmap 来实现它,并且它已经奏效了。 KStream 输出 = trademessage.flatMapValues(tradedata -> tradedata.getTradedatas());列表 output1 = new ArrayList(); output.foreach((key,value)->System.out.println(String.format("%d,%s" ,value.getClientid(),value.getBooking().getAccountid())));我想检查是否有任何方法可以将单个列的数据存储到 JSON/Avro 中的 Kafka 主题中?我想使用 Kafka Connect 读取此输出数据并将其存储在数据库中。我也接受了你的回答。
    猜你喜欢
    • 2017-07-28
    • 1970-01-01
    • 2017-06-22
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    • 2018-09-30
    • 2019-08-04
    • 1970-01-01
    相关资源
    最近更新 更多