Java Spark-任务不可序列化:如何处理调用外部类/对象的复杂映射闭包?

Java Spark-任务不可序列化:如何处理调用外部类/对象的复杂映射闭包?,java,scala,serialization,apache-spark,Java,Scala,Serialization,Apache Spark,看看这个问题: 问题: 假设我的映射器可以是函数(def),在内部调用其他类,创建对象,并在内部执行不同的操作。(或者它们甚至可以是扩展(Foo)=>Bar并在其apply方法中进行处理的类——但现在让我们忽略这种情况) Spark只支持闭包的Java序列化。有办法解决这个问题吗?我们可以用一些东西代替闭包来做我想做的事情吗?我们可以很容易地用Hadoop做这类事情。这件事让Spark对我来说几乎无法使用。不能期望所有第三方库都具有可扩展序列化的所有类 可能的解决方案: 像这样的东西有什么用处吗

看看这个问题:

问题:

假设我的映射器可以是函数(def),在内部调用其他类,创建对象,并在内部执行不同的操作。(或者它们甚至可以是扩展(Foo)=>Bar并在其apply方法中进行处理的类——但现在让我们忽略这种情况)

Spark只支持闭包的Java序列化。有办法解决这个问题吗?我们可以用一些东西代替闭包来做我想做的事情吗?我们可以很容易地用Hadoop做这类事情。这件事让Spark对我来说几乎无法使用。不能期望所有第三方库都具有可扩展序列化的所有类

可能的解决方案:

像这样的东西有什么用处吗:


当然,答案似乎是用包装纸,但我看不出确切的答案。

我自己就知道怎么做了

只需在传递闭包之前序列化对象,然后反序列化即可。这种方法很有效,即使您的类不可序列化,因为它在幕后使用Kryo。你所需要的只是一些咖喱

以下是我如何做到这一点的示例:

def genMapper(kryoWrapper: KryoSerializationWrapper[(Foo => Bar)])
               (foo: Foo) : Bar = {
    kryoWrapper.value.apply(foo)
}
val mapper = genMapper(KryoSerializationWrapper(new Blah(abc))) _
rdd.flatMap(mapper).collectAsMap()

object Blah(abc: ABC) extends (Foo => Bar) {
    def apply(foo: Foo) : Bar = { //This is the real function }
}
您可以随意使Blah变得复杂,比如类、伴随对象、嵌套类、对多个第三方lib的引用


KryoSerializationWrapper引用:

如果使用Java API,在传递到映射函数闭包时应该避免匿名类。您需要一个类来扩展您的函数并将其传递给map(..),而不是执行map(新函数) 见:

另一种选择是在Blah类本身中实现可序列化接口。再想一想,wrapper使它更灵活,如果您愿意,可以切换到不同类型的序列化。@SKP这就是问题的关键所在。事实证明,不仅Blah,Blah的实例字段也需要扩展Serializable—这是显而易见的,因为所有内容都将以递归方式存储。如果您的类使用第三方库并修改它们的代码会给您带来噩梦,该怎么办?这就是像这样的东西派上用场的地方。此外,Java序列化很慢。相关:另外,避免将SparkContext传递到RDD映射/过滤器/平面映射等转换中,这可能会产生类似的错误。当你说类扩展了你的函数时,我想扩展作为接口的VoidFunction,我在这里有点困惑。。我需要实现还是扩展,如果我需要扩展,我需要实际创建接口,对吗?在那个特定的示例中,您需要扩展PairFunction。不需要实现交错。地图采取(配对函数f)或(函数f)你能在这里举个例子吗?网站被暂停了,你能给我们举个例子吗?如果我正确理解你的答案,不,这不起作用。