Scala Spark将变量值序列化为null,而不是其实际值

Scala Spark将变量值序列化为null,而不是其实际值,scala,apache-spark,apache-spark-2.2,Scala,Apache Spark,Apache Spark 2.2,我对Spark的代码向运行它的节点的分布机制的理解只是粗略的,当我希望为每个分区实例化一个类时,我无法让我的代码在Spark的mapPartitionsAPI中成功运行,并带有一个参数 下面的代码工作得很好,直到我将类MyWorkerClass演化为需要参数: val result : DataFrame = inputDF.as[Foo].mapPartitions(sparkIterator => { // (1) initialize heavy class

我对Spark的代码向运行它的节点的分布机制的理解只是粗略的,当我希望为每个分区实例化一个类时,我无法让我的代码在Spark的
mapPartitions
API中成功运行,并带有一个参数

下面的代码工作得很好,直到我将类
MyWorkerClass
演化为需要参数:

  val result : DataFrame =
    inputDF.as[Foo].mapPartitions(sparkIterator => {

      // (1) initialize heavy class instance once per partition
      val workerClassInstance = MyWorkerClass(bar)

      // (2) provide an iterator using a function from that class instance
      new CloseableIteratorForSparkMapPartitions[Post, Post](sparkIterator, workerClassInstance.recordProcessFunc)
    }
在我(或选择)向类添加构造函数参数之前,上面的代码工作得非常好。传递的参数值在worker中显示为
null
,而不是
bar
的实际值。不知何故,参数的序列化未能按预期工作

你会怎么做


其他想法/意见 我将避免添加大型代码
CloseableIteratorForSparkMapPartitions
——它只提供了一个Spark友好的迭代器,甚至可能不是其中最优雅的实现

据我所知,构造函数参数没有正确地传递给Spark worker,这是因为Spark在序列化要发送以在Spark worker上执行的内容时如何捕获状态。然而,实例化该类确实无缝地使该类中包含的重载资产——通常可用于我上面代码最后一行中提供的函数;这个类似乎是按每个分区实例化的。对于使用
mapPartitions
而不是
map
,这实际上是一个有效的(如果不是关键的话)用例

这是一个参数到它的实例化的传递,我很难理解如何启用或解决它。在我的例子中,这个参数是一个只有在程序开始运行后才知道的值(即使在我的作业的单个执行过程中始终不变;它实际上是一个程序参数)。我确实需要在初始化类时传递它

我试图通过提供一个用输入参数实例化
MyWorkerClass
的函数来解决这个问题,而不是像上面那样直接实例化,但这并没有解决问题

问题的根本症状不是任何异常,而是当实例化
MyWorkerClass
时,
bar
的值将只是
null
,而不是
bar
的实际值,这在我上面包含的代码段的代码范围内是已知的


*一个相关的
val workerclass实例:MyWorkerClass(bar)
它是有效的初始化吗?它不应该是
val workerclass实例:MyWorkerClass=MyWorkerClass(bar)
?在
mapPartitions
的范围内,Spark知道
MyWorkerClass
的构造函数,但是
bar
呢?您在哪里申报
条码
?还有,你到底得到了什么错误?我明白了,我认为问题是Spark没有意识到在驱动程序代码期间发生的赋值。例如,您可以尝试在mapPartitions之前为bar分配一个虚拟值,例如
bar=Some(“哇”)
,甚至广播它:)Spark在将闭包发送给执行者之前对闭包进行一些清理。也许这会弄乱Option[T]实例的值。我会尝试在闭包外初始化对象,并且几乎总是使用
val
而不是
var
(这在您已经发送的第一个实例中讨论)。最后,不要忘记继承
Serializable
类。当然,如果您得出任何结论,请告诉我们:)
val workerclass实例:MyWorkerClass(bar)
这是有效的初始化吗?它不应该是
val workerclass实例:MyWorkerClass=MyWorkerClass(bar)
?在
mapPartitions
的范围内,Spark知道
MyWorkerClass
的构造函数,但是
bar
呢?您在哪里申报
条码
?还有,你到底得到了什么错误?我明白了,我认为问题是Spark没有意识到在驱动程序代码期间发生的赋值。例如,您可以尝试在mapPartitions之前为bar分配一个虚拟值,例如
bar=Some(“哇”)
,甚至广播它:)Spark在将闭包发送给执行者之前对闭包进行一些清理。也许这会弄乱Option[T]实例的值。我会尝试在闭包外初始化对象,并且几乎总是使用
val
而不是
var
(这在您已经发送的第一个实例中讨论)。最后,不要忘记继承
Serializable
类。当然,如果您得出任何结论,请让我们知道:)