火花工人之间的代码共享

时间:2016-07-05 12:19:52

标签: scala apache-spark

根据Spark文档,最好在RDD转换中使用匿名或scala对象函数。我有下一个代码的对象:

object Util {
  val someManager = new Manager()

  def process(data: String) = someManager.manage(data)
}

我接下来称之为:

myRDD.map(Util.process)

如何将Util对象序列化并发送给spark worker?管理员是否会每次或每次只发送一次?将经理人的实例多少次发送给工人?

2 个答案:

答案 0 :(得分:2)

  

如何将Util对象序列化并发送给spark worker?是否   管理员将被创建为每次或仅一次发送?多少   经理的实例将被派往火花工人?

Util.process在编译时包含在AbstractFunction1内,它实现了apply方法,这是序列化的方法。您可以在反编译此代码时看到这一点(这是从JVM字节代码重建的):

par.map(new AbstractFunction1() {
  public static final long serialVersionUID = 0L;

  public final void apply(String data)
  {
    Util..MODULE$.process(data);
  }
 }, ClassTag..MODULE$.Unit());
}

我们想要看到的另一件事是如何将Util对象编译成字节代码:

public final class Util$
{
  public static final  MODULE$;
  private final Manager someManager;

  public Manager someManager()
  {
    return this.someManager;
  }

  private Util$()
  {
    MODULE$ = this;
    this.someManager = new Manager();
  }

  public void process(String data)
  {
    someManager().manage(data);
  }
}

这意味着我们仍然有Manager的实例字段。会发生什么事情,Spark将使用它ClosureCleaner来清除Util的实例,因为它不需要它,但是它需要将Manager实例序列化为工人,每次它都需要调用map。这并不意味着会有多个Manager实例,它只是意味着需要对单个实例进行序列化并通过线路发送。我们可以在ClosureCleaner的文档中看到详细信息:

  
      
  • 机制是遍历封闭闭包的层次结构,并且将所有未实际使用的引用中的任何引用置空   通过开始闭合,但仍包括在   编译匿名类。请注意,简单地说它是不安全的   将封闭的闭包变异,就像其他代码路径可能依赖的那样   在他们。相反,我们克隆每个封闭的闭包并设置   相应的父指针。
  •   

答案 1 :(得分:-1)

Util需要可序列化,否则你会得到一个例外。经理将每次发送,例如每项任务。您只能为每个分区发送一次,为此您需要先播放它,请参阅http://spark.apache.org/docs/latest/programming-guide.html