关于Flink反序列化的两个问题

时间:2017-06-12 00:29:29

标签: java json deserialization apache-flink json-ld

我是Flink和集群计算的新手。我花了一整天的时间试图在Flink上正确解析来自Kafka的愚蠢流,没有结果:这有点让人沮丧...... 我在kafka中发现了一个用字符串键标识的JSON-LD消息流。我只想在Flink中检索它们,然后用不同的密钥分隔消息。

1) 最初我考虑将消息发送为String而不是JSON-LD。我觉得更容易......

我尝试了所有deserialiser,但都没有。简单的解串器无效但却完全忽略了键。

我相信我必须使用(Flink显然只有两个支持密钥的解串器):

DataStream<Object> stream = env
            .addSource(new FlinkKafkaConsumer010<>("topicTest", new TypeInformationKeyValueSerializationSchema(String.class, String.class, env.getConfig()), properties))
            .rebalance();

    stream.print();

但我得到了:

  

06/12/2017 02:09:12来源:Custom Source(4/4)切换为FAILED   java.io.EOFException的       at org.apache.flink.runtime.util.DataInputDeserializer.readUnsignedByte(DataInputDeserializer.java:306)

如何在不丢失密钥的情况下接收流消息?

2) 我的kafka生成器是用javascript实现的,因为Flink支持JSONDeserialization我虽然直接发送kafka JSON Object。 我不确定JSON-LD能否正常使用,但我已经使用过:

json.parse(jsonld_message)

将json序列化为消息。然后我用普通的字符串键发送了它。

但是在Flink中,这段代码不起作用:

DataStream<ObjectNode> stream = env
            .addSource(new FlinkKafkaConsumer010<>("topicTest", new JSONKeyValueDeserializationSchema(false), properties))
            .rebalance();

    stream.print();

提高

  

JsonParserException。

我认为第一种方法更简单,我更喜欢它,因为允许及时考虑一个问题(第一种:接收数据,第二种:在JSON-LD中重新转换字符串,我想是外部库)。

3 个答案:

答案 0 :(得分:0)

为了使用Flink的TypeInformationKeyValueSerializationSchema从Kafka读取数据,必须以兼容的方式编写。假设您的密钥和值的类型为String,那么密钥和值必须以Flink的StringSerializer理解数据的方式编写。

因此,您必须确保您的Kafka生产者以兼容的方式写入数据。否则Flink'将无法读取数据。

答案 1 :(得分:0)

解决:

最后,我决定实现一个实现KeyedDeserializedSchema接口的自定义反序列化器。

答案 2 :(得分:0)

** 我遇到了类似的问题。理想情况下,带有键和值的字符串类型的 TypeInformationKeyValueSerializationSchema 应该能够读取我的 kafka 记录,该记录将键和值作为字符串。但正如上面的帖子所指出的那样,它无法并且有一个 EOF 异常。所以这个问题很容易重现,需要修复。请让我知道我是否可以在此过程中提供任何帮助。同时使用

实现自定义序列化程序 <块引用>

Kafka 解串器架构

。这是代码,因为关于它读取键/值和其他内容的文档很少: **

import org.apache.flink.api.common.typeinfo.TypeHint;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.connectors.kafka.KafkaDeserializationSchema;

import org.apache.kafka.clients.consumer.ConsumerRecord;

public class CustomKafkaSerializer implements KafkaDeserializationSchema<Tuple2<String,String>> {


    @Override
    public boolean isEndOfStream(Tuple2<String,String> stringStringPair) {
        return false;
    }

    @Override
    public Tuple2<String,String> deserialize(ConsumerRecord<byte[], byte[]> consumerRecord) throws Exception {
        String key = new String(consumerRecord.key());
        String value = new String(consumerRecord.value());
        return new Tuple2<>(key,value);
    }

    @Override
    public TypeInformation<Tuple2<String,String>> getProducedType() {
        return TypeInformation.of(new TypeHint<Tuple2<String, String>>(){});
    }

}