关于kryo序列化我缺少什么?
Class1和Class3不是java可序列化类(没有默认构造函数,既不是getter也不是setter)
当我尝试“使用”一个实例,这是由Spark内部创建的,在Spark中,我得到一个序列化问题,无论我是否将Classe3注册为Kryo类。
工作良好:
Dataset<Class1> ds = spark.createDataset(classes, Encoders.kryo(Class1.class));
Dataset<String> df = df.map((MapFunction<Class1, String>) class1 -> class1.getName(), Encoders.STRING());
df.show();
Class3引起的序列化错误
spark = SparkSession
.builder()
.master("local[*]")
.config(new SparkConf().registerKryoClasses(new Class[] {Class3.class}))
.appName("spark_test")
.getOrCreate();
Class3 class3 = Class3.getInstance();
Dataset<Class1> ds = spark.createDataset(classes, Encoders.kryo(Class1.class));
Dataset<String> df = df.map((MapFunction<Class1, String>) class1 -> class1.getName() + "-" class3.getId(), Encoders.STRING());
df.show();
总结评论中发生的讨论以形成答案 - 当您尝试调用转换时,Spark驱动程序必须为该转换中的代码创建并发送一个闭包给负责运行它的执行程序。 。在您的情况下,代码行Class3 class3 = Class3.getInstance();
是Scala对象的一部分,它包含Spark上下文的创建和使用,以获得一些结果,即驱动程序应用程序。因此,当您尝试在映射转换中传递class3
时,驱动程序正在尝试序列化封闭的Scala对象。除非您实现序列化,否则此scala对象本身不是Serializable,因此您将遇到序列化问题。
Re:Kryo序列化 - 因为您已经使用Kryo注册了Class3,它将帮助您序列化Class3实例,但是它不会将具有Class3实例的Composite对象序列化为变量。
因此,如果您提取class3.getId()
的值然后将其传递给地图转换,则不需要在Kryo中注册Class3。
在您的示例中,我在上面提到的Scala对象与Driver应用程序相同。
希望这可以帮助。