Spark如何向工人发送关闭?

时间:2015-08-14 17:22:16

标签: apache-spark

当我写RDD转换时,例如

val rdd = sc.parallelise(1 to 1000) 
rdd.map(x => x * 3)

我理解只是一个Function1的闭包(x => x * 3)需要是Serializable并且我想我在某处读到了 编辑:它正好在文档中暗示: http://spark.apache.org/docs/latest/programming-guide.html#passing-functions-to-spark 它被“发送”给工人执行。 (例如,Akka向线路工作人员发送“可执行的一段代码”)

这是怎么回事?

有人参加了聚会,我参加了评论并说它实际上并没有发送任何序列化的代码,但是因为每个工作者都得到了jar的“副本”,所以它只需要引用哪个函数来运行或类似这样的东西(但我不确定我是否正确引用了那个人)

我现在对它的实际运作方式感到十分困惑。

所以我的问题是

  1. 如何向工人发送转型关闭?通过akka序列化?或者他们“已经在那里”,因为火花将整个超级罐发送给每个工人(听起来不太可能......)

  2. 如果是这样,那么罐子的其余部分如何发送给工人?这是“cleanupClosure”在做什么?例如只发送相关的字节码给工人而不是整个uberjar? (例如,只有关闭的依赖代码?)

  3. 总而言之,在任何时候都会引发--jars类路径中的jar与工作者的某种程度的同步?或者它是否向工人发送“恰当数量”的代码?如果确实发送了闭包,是否需要重新计算它们?或者每次安排任务时是否发送关闭任务?对不起,如果这是愚蠢的问题,但我真的不知道。

  4. 如果可以提供答案,请添加来源,我在文档中找不到它,我太谨慎了,只是通过阅读代码来尝试结束它。

1 个答案:

答案 0 :(得分:2)

闭包在运行时肯定是序列化的。我有很多实例在运行时看到Closure Not Serializable异常 - 来自pyspark和scala。有一个叫做

的复杂代码

来自ClosureCleaner.scala

def clean(
    closure: AnyRef,
    checkSerializable: Boolean = true,
    cleanTransitively: Boolean = true): Unit = {
  clean(closure, checkSerializable, cleanTransitively, Map.empty)
}

试图缩小被序列化的代码。然后通过线路发送代码 - 如果它是可序列化的。否则将抛出异常。

以下是ClosureCleaner的另一段摘录,用于检查序列化传入函数的能力:

  private def ensureSerializable(func: AnyRef) {
    try {
      if (SparkEnv.get != null) {
        SparkEnv.get.closureSerializer.newInstance().serialize(func)
      }
    } catch {
      case ex: Exception => throw new SparkException("Task not serializable", ex)
    }
  }