Spark Scala动态创建Serializable对象

时间:2017-04-08 11:03:35

标签: java scala apache-spark serialization serializable

我需要使用Scala Spark过滤器的测试器,测试器实现java的Predicate接口并通过参数接收特定的类名。 我正在做这样的事情

val tester = Class.forName(qualifiedName).newInstance().asInstanceOf[Predicate[T]]
var filtered = rdd.filter(elem => tester.test(elem))

问题是在运行时我有一个Spark“TaskNotSerializable Exception”,因为我的特定Predicate类不是Serializable。

如果我这样做

val tester = Class.forName(qualifiedName).newInstance()
             .asInstanceOf[Predicate[T] with Serializable]
var filtered = rdd.filter(elem => tester.test(elem))

我得到了同样的错误。 如果我在rdd.filter中创建测试程序,它就会起作用:

var filtered = rdd.filter { elem => 
    val tester = Class.forName(qualifiedName).newInstance()
             .asInstanceOf[Predicate[T] with Serializable]
    tester.test(elem)
}

但我会创建一个对象(可能是广播)进行测试。我该如何解决?

1 个答案:

答案 0 :(得分:0)

您只需要要求类实现Serializable。请注意,asInstanceOf[Predicate[T] with Serializable]强制转换是谎言:它实际上并不检查值是Serializable,这就是为什么第二种情况不会在演员表中立即产生错误,而最后一个“成功” ”

  

但我会创建一个对象(可能是广播)进行测试。

你做不到。是否广播,反序列化将在工作节点上创建 new 对象。但是,您只能在每个分区上创建一个实例:

var filtered = rdd.mapPartitions { iter => 
    val tester = Class.forName(qualifiedName).newInstance()
             .asInstanceOf[Predicate[T]]
    iter.filter(tester.test)
}

它实际上比序列化tester,发送它和反序列化更好,因为它的工作量非常少。