Serialization Flink Kafka producer:类的对象不可序列化

Serialization Flink Kafka producer:类的对象不可序列化,serialization,apache-kafka,apache-flink,Serialization,Apache Kafka,Apache Flink,我尝试为我的定制类实现一个方法,使用Flink-Kafka连接器生成关于Kafka的数据。类原型如下所示: public class StreamData implements Serializable { private transient StreamExecutionEnvironment env; private DataStream<byte[]> data ; ... 主要代码: StreamData temp = new StreamData(

我尝试为我的定制类实现一个方法,使用Flink-Kafka连接器生成关于Kafka的数据。类原型如下所示:

public class StreamData implements Serializable {
    private transient StreamExecutionEnvironment env;
    private DataStream<byte[]> data ;
    ...
主要代码:

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


如何消除错误?

使
数据
属性为静态,解决了问题。有人能详细说明一下吗?这是一个好的解决方案吗

private static DataStream<byte[]> data ;
私有静态数据流数据;

使
数据
属性为静态,解决了问题。有人能详细说明一下吗?这是一个好的解决方案吗

private static DataStream<byte[]> data ;
私有静态数据流数据;

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

new KeyedSerializationSchema<byte[]>() {...}
newkeyedSerializationSchema(){…}
这段代码的作用是创建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);
    }
}
公共类流数据{
静态KeyedSerializationSchema模式=新KeyedSerializationSchema(){
...
};
...
public void writedaintaintoesb(字符串id)引发异常{
FlinkKafkaProducer011 producer=新的FlinkKafkaProducer011(“本地主机:9092”,id,模式);
data.addSink(生产者);
}
}

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

new KeyedSerializationSchema<byte[]>() {...}
newkeyedSerializationSchema(){…}
这段代码的作用是创建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);
    }
}
公共类流数据{
静态KeyedSerializationSchema模式=新KeyedSerializationSchema(){
...
};
...
public void writedaintaintoesb(字符串id)引发异常{
FlinkKafkaProducer011 producer=新的FlinkKafkaProducer011(“本地主机:9092”,id,模式);
data.addSink(生产者);
}
}

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

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

公共类CustomSerializerSchema实现SerializationSchema{
私有静态最终长serialVersionUID=1L;
@凌驾
公共字节[]序列化(MyUser元素){
字节[]b=null;
试一试{
b=新的ObjectMapper().writeValueAsBytes(元素);
}捕获(JsonProcessingException e){
e、 printStackTrace();
}
返回b;
}
}

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

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

公共类CustomSerializerSchema实现SerializationSchema{
私有静态最终长serialVersionUID=1L;
@凌驾
公共字节[]序列化(MyUser元素){
字节[]b=null;
试一试{
b=新的ObjectMapper().writeValueAsBytes(元素);
}捕获(JsonProcessingException e){
e、 printStackTrace();
}
返回b;
}
}

我认为问题在于,当它试图创建您的实际执行环境时,它需要能够将所有内容序列化到作业管理器中,但您将数据流嵌套在对象中,因此无法很好地转换。您是否能够尽可能多地编辑您的示例,并在您认为合适的情况下进行消毒?很难确切地看出你想做什么,但我认为这与你的问题无关Kafka@JoshuaDeWald正如我所说的,这是因为Java或Flink的特性,因为我在
main
函数中测试了相同的代码,但没有类,所以它可以工作。其他方法,如读取卡夫卡或在卡桑德拉上写入数据,效果很好,只是将数据写入卡夫卡的方法不起作用!我认为问题在于,当它试图创建实际的执行环境时,它需要能够将所有内容序列化到作业管理器中,但是您将数据流嵌套在对象中,因此这不会很好地转换。您是否能够尽可能多地编辑您的示例,并在您认为合适的情况下进行消毒?很难确切地看出你想做什么,但我认为这与你的问题无关Kafka@JoshuaDeWald正如我所说的,这是因为Java或Flink的特性,因为我在
main
函数中测试了相同的代码,但没有类,所以它可以工作。其他方法,如读取卡夫卡或在卡桑德拉上写入数据,效果很好,只是将数据写入卡夫卡的方法不起作用!你对我的解决方案有什么想法:改变fi