我一直在阅读Spark的源代码,但我仍然无法理解Spark独立如何实现资源隔离和分配。例如,Mesos使用LXC或Docker来实现容器以进行资源限制。那么Spark Standalone如何实现这一点呢。例如,我在一个执行程序中运行了10个线程,但Spark只给执行程序一个核心,那么Spark如何保证这10个线程只在一个cpu核心上运行。
在以下测试代码之后,事实证明Spark Standalone资源分配在某种程度上是伪造的。我只有一个Worker(执行程序),只给执行程序一个核心(机器总共有6个核心),当下面的代码运行时,我发现有5个核心100%使用。 (我的代码启动了4个帖子)
object CoreTest {
class MyThread extends Thread {
override def run() {
while (true) {
val i = 1+1
}
}
}
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("core test")
val sc = new SparkContext(conf)
val memRDD = sc.parallelize(Seq(1), 1)
memRDD.foreachPartition { part =>
part.foreach {
x =>
var hello = new MyThread()
hello.start
hello = new MyThread()
hello.start
hello = new MyThread()
hello.start
hello = new MyThread()
hello.start
while (true) {
val j = 1+2
Thread.sleep(1000)
}
}
}
sc.stop()
}
}
以下问题:我很好奇,如果我在Spark + Mesos上运行上述代码,会发生什么,Mesos会限制仅在一个核心上运行的4个线程。
答案 0 :(得分:4)
但我仍然无法理解Spark独立如何实现资源隔离和分配。
使用Spark,我们有一个Master节点和Worker节点的表示法。我们可以将后者视为资源池。每个worker都有CPU和RAM,它带来了池,Spark作业可以利用该池中的资源进行计算。
Spark Standalone具有Executor的表示法,Executor是处理计算的过程,我们从资源池中提供资源。在任何给定的执行程序中,我们运行由不同任务组成的计算的不同阶段。现在,我们可以控制给定任务使用的计算能力(核心)量(通过spark.tasks.cpu
配置参数),并且我们还可以控制给定作业可能具有的一般计算能力(通过spark.cores.max
,它告诉集群管理器我们想要为我们正在运行的特定作业提供多少总计的资源。请注意,默认情况下Standalone是最安全的,并将在群集中的每个Worker节点上安排执行程序。我们可以使用Dynamic Allocation对我们拥有的实际执行者数量进行更精细的控制。
例如,我在一个执行程序中运行了10个线程,但是Spark只给执行程序一个核心,所以Spark如何保证这10个线程只在一个cpu核心上运行。
Spark不会验证执行只发生在单个核心上。 Spark不知道它将从底层操作系统获得哪个CPU周期。 Spark Standalone尝试做的是资源管理,它告诉你“看,你有X量的CPU和Y量的RAM,如果你没有正确地划分你的资源,我不会让你安排工作”。
答案 1 :(得分:2)
Spark Standalone仅处理资源分配,这是一项简单的任务。所需要的就是密切关注:
它不会处理资源隔离。具有更广范围的YARN和Mesos不实现资源隔离,而是依赖于Linux控制组(cgroups
)。