Flink Kafka生产者:类的对象不可序列化

时间:2018-03-31 15:53:39

标签: serialization apache-kafka apache-flink

我尝试为自定义类实现一个方法,使用Flink Kafka连接器在Kafka上生成数据。类原型如下:

public class StreamData implements Serializable {
    private transient StreamExecutionEnvironment env;
    private DataStream<byte[]> data ;
    ...

将数据写入特定Kafka主题的方法如下:

public void writeDataIntoESB(String id) throws Exception {

        FlinkKafkaProducer011<byte[]> producer = new FlinkKafkaProducer011<byte[]>(
                "localhost:9092",
                id,
                new KeyedSerializationSchema<byte[]>() {
                    @Override
                    public byte[] serializeKey(byte[] bytes) {
                        return bytes;
                    }

                    @Override
                    public byte[] serializeValue(byte[] bytes) {
                        return bytes;
                    }

                    @Override
                    public String getTargetTopic(byte[] bytes) {
                        return null;
                    }
                });               
        data.addSink(producer);
    }

我有另一种方法可以将数据从Kafka主题获取到对象的data字段,这样可以正常工作。现在尝试从Kafka主题获取数据并将其写入另一个Kafka主题我得到了错误:

org.apache.flink.api.common.InvalidProgramException: Object StreamData$2@1593948d is not serializable

主要代码:

StreamData temp = new StreamData();
temp = temp.getDataFromESB("data", 0);
temp.writeDataIntoESB("flink_test");

似乎Java试图序列化对象而不仅仅是字段data!使用Flink Kafka连接器向Kafka生成数据的代码经过测试,可以正常使用(我的意思是不使用类并在main中编写所有代码)

我怎样才能消除错误?

3 个答案:

答案 0 :(得分:2)

我认为问题的原因是您的代码正在执行此操作:

new KeyedSerializationSchema<byte[]>() {...}

这段代码的作用是创建一个KeyedSerializationSchema的匿名子类作为定义类(StreamData)的内部类。每个内部类都包含对外部类实例的隐式引用,因此使用默认Java序列化规则对其进行序列化也将传递尝试序列化外部对象(StreamData)。解决此问题的最好方法是将KeyedSerializationSchema的子类声明为:

我认为最后一种方法看起来像这样:

public class StreamData {
    static KeyedSerializationSchema<byte[]> schema = new KeyedSerializationSchema<byte[]>() {
        ...
    };
    ...
    public void writeDataIntoESB(String id) throws Exception {

        FlinkKafkaProducer011<byte[]> producer = new FlinkKafkaProducer011<byte[]>("localhost:9092", id, schema);               
        data.addSink(producer);
    }
}

答案 1 :(得分:0)

data属性设为静态,解决了问题。任何人都可以详细说明这个并且它是一个很好的解决方案吗?

private static DataStream<byte[]> data ;

答案 2 :(得分:0)

您也可以像这样在Flink中进行序列化

dataStream.addSink(new FlinkKafkaProducer<KafkaObject>(ProducerTopic, new 
                                             CustomSerializerSchema(),properties));

  public class CustomSerializerSchema implements SerializationSchema<MyUser> {

    private static final long serialVersionUID = 1L;

    @Override
    public byte[] serialize(MyUser element) {
        byte[] b = null;
         try {
             b= new ObjectMapper().writeValueAsBytes(element);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return b; 
    }
}