为什么当我有两个Worker节点时,Spark Standalone只创建一个Executor?

时间:2017-06-16 18:25:55

标签: java apache-spark

首先,我是否从根本上误解了Spark Standalone模式?官方文件说

  

独立群集模式目前仅支持简单的FIFO   跨应用程序的调度程序但是,要允许多个并发   用户,可以控制每个资源的最大数量   应用程序将使用。

我认为这意味着多个用户可以并行运行应用程序,将作业提交到同一个Spark Standalone集群。但是,现在我想知道这是否意味着限制资源将允许多个用户分别运行单独的Spark Standalone集群而不会使所有其他用户挨饿(或者只是在集群上运行其他程序而不会使Spark缺乏资源)。是这种情况吗?

我在运行Ubuntu的三个虚拟机上以独立模式设置Spark。他们都可以通过NAT网络看到对方。其中一台机器(192.168.56.101)是主机,而其他机器是从机(192.168.56.102192.168.56.103)。

Spark版本是2.1.7。

我有一个Java应用程序,它在几个线程中创建JavaRDD对象,每个线程在自己的线程中调用.collect()。我原以为这就算是一种"工作"哪个可以并行运行单个Spark Context对象(根据https://spark.apache.org/docs/1.2.0/job-scheduling.html)。

每个线程从一个类的同步方法获取一个JavaRDD对象,该方法协调对(单个)JavaSparkContext对象的访问。 JavaSparkContext的设置没有太多调整。基本上它是

public synchronized JavaRDD<String> getRdd(List<String> fooList) {
  if (this.javaSparkContext == null) {
    SparkConf sparkConf = new SparkConf();
    sparkConf.set("spark.executor.memory", "500m");
    // There might be a few more settings here such as host name and port, but nothing directly to do with an executor pool or anything, as far as I remember. I don't have the code in front of me while not at work.
    this.javaSparkContext = JavaSparkContext.fromSparkContext(new SparkContext(sparkConf));
  }

  if (this.jobPool == "fooPool") {
    this.jobPool = "barPool";
  } else {
    this.jobPool = "fooPool";
  }

  this.javaSparkContext.setLocalProperty("spark.scheduler.pool", this.jobPool);

  this.javaSparkContext.requestExecutors(1);
  return this.javaSparkContext.parallelize(fooList);
}

Spark Context对象设置了两个作业池(正如我设置的那样),据我所知,从控制台日志中可以看出:

... INFO scheduler.FairSchedulableBuilder: Created pool fooPool, schedulingMode: FAIR, minShare: 1, weight: 1
... INFO scheduler.FairSchedulableBuilder: Created pool barPool, schedulingMode: FAIR, minShare: 1, weight: 1
... INFO scheduler.FairSchedulableBuilder: Created pool default, schedulingMode: FIFO, minShare: 1, weight: 1

我创建了很多线程,每个线程提交一个.collect()作业,在两个FAIR池之间交替。据我所知,这些被分配到两个池:

... INFO: scheduler.TaskSchedulerImpl: Adding task set 0.0 with 1 tasks
... INFO scheduler.FairSchedulableBuilder: Added task set TaskSet_0.0 tasks to pool fooPool

等等,在两个池之间交替。

.collect()来电就像

List<String> consoleOutput = getRdd(fooList).cache().pipe("python ./dummy.py").collect();

但我再也没有在我面前提供代码。它肯定适用于Executor正确执行命令的意义。)

但是,client.StandaloneAppClient $ ClientEndpoint只创建一个Executor,然后继续执行barPool中的所有任务,然后执行fooPool中串行(但不是FIFO)的所有任务。虽然我设置了SPARK_EXECUTOR_INSTANCES, SPARK_EXECUTOR_CORES, SPARK_WORKER_INSTANCES,SPARK_WORKER_CORES to 4,但是工作节点VM有1个核心,希望这会有所帮助。

主节点也将SPARK_EXECUTOR_INSTANCES, SPARK_EXECUTOR_CORES, SPARK_WORKER_INSTANCES,SPARK_WORKER_CORES设置为4。

只有一个Worker节点响应,并且只发送一个Executor。两个Worker节点都可以与Master通信 - 我可以关闭一个,另一个将占用我提交的下一组作业。

这些工作是微不足道的工作,每个工作都提供一个Python脚本,可以执行几秒钟的休眠,打印一些东西&#34;,每个工作都需要一个单元素的RDD,作为概念的证明。一个很好的商业原因,因为基本上多个不相关的RDD需要由不相关的Python脚本并行处理。

我错过了一些设置吗?我知道我误用了Spark,因为我特别阻止它根据RDD进行并行化,但这是一成不变的。令我感到困惑的是,在多个工作池中,只有一个工作人员响应,因为有许多任务集排成一行。我甚至会在每次提交时调用.requestExecutors(1),控制台显示

... INFO cluster.StandaloneSchedulerBackend: Requesting 1 additional executor(s) from the cluster manager

但这似乎完全被忽略了。

任何建议都将不胜感激!

编辑:为方法设置上下文添加了Spark版本和Java代码。删除那些认为他们会纠正&#34;的人所引入的愚蠢的英语错误。我的问题是语法上的错误,这些问题得到了一些显然没有阅读编辑的人的认可。

1 个答案:

答案 0 :(得分:0)

就我在互联网上的大量研究和我自己的代码进行实验而言,我的答案是&#34; Spark不会那样工作&#34;。

具体做法是: 1)每个Java虚拟机只能有1个Spark上下文。 2)Per Spark Context,任务只能按顺序执行。

流行的Spark集群管理器(如Mesos或Mist)使用的方法是准备几个Spark上下文,每个上下文都在自己的JVM中,任务分配在这些Spark上下文中。

我可以通过使用第二个JVM来管理第二个工作者(在我的例子中,它是通过在Eclipse调试器和IntelliJ调试器中同时运行相同的代码),但这只是对这种类型的确认。如上所述的设置。