Skip to content
Snippets Groups Projects
Commit e2a67a80 authored by Matei Zaharia's avatar Matei Zaharia
Browse files

Fixes to coarse-grained Mesos scheduler in dealing with failed nodes

parent be622cf8
No related branches found
No related tags found
No related merge requests found
...@@ -112,7 +112,7 @@ class StandaloneSchedulerBackend(scheduler: ClusterScheduler, actorSystem: Actor ...@@ -112,7 +112,7 @@ class StandaloneSchedulerBackend(scheduler: ClusterScheduler, actorSystem: Actor
masterActor ! ReviveOffers masterActor ! ReviveOffers
} }
def defaultParallelism(): Int = totalCoreCount.get() def defaultParallelism(): Int = math.max(totalCoreCount.get(), 2)
} }
object StandaloneSchedulerBackend { object StandaloneSchedulerBackend {
......
...@@ -41,6 +41,8 @@ class CoarseMesosSchedulerBackend( ...@@ -41,6 +41,8 @@ class CoarseMesosSchedulerBackend(
"SPARK_JAVA_OPTS" "SPARK_JAVA_OPTS"
) )
val MAX_SLAVE_FAILURES = 2 // Blacklist a slave after this many failures
// Memory used by each executor (in megabytes) // Memory used by each executor (in megabytes)
val executorMemory = { val executorMemory = {
if (System.getenv("SPARK_MEM") != null) { if (System.getenv("SPARK_MEM") != null) {
...@@ -67,6 +69,9 @@ class CoarseMesosSchedulerBackend( ...@@ -67,6 +69,9 @@ class CoarseMesosSchedulerBackend(
val slaveIdsWithExecutors = new HashSet[String] val slaveIdsWithExecutors = new HashSet[String]
val taskIdToSlaveId = new HashMap[Int, String]
val failuresBySlaveId = new HashMap[String, Int] // How many times tasks on each slave failed
val sparkHome = sc.getSparkHome() match { val sparkHome = sc.getSparkHome() match {
case Some(path) => case Some(path) =>
path path
...@@ -161,10 +166,14 @@ class CoarseMesosSchedulerBackend( ...@@ -161,10 +166,14 @@ class CoarseMesosSchedulerBackend(
val mem = getResource(offer.getResourcesList, "mem") val mem = getResource(offer.getResourcesList, "mem")
val cpus = getResource(offer.getResourcesList, "cpus").toInt val cpus = getResource(offer.getResourcesList, "cpus").toInt
if (totalCoresAcquired < maxCores && mem >= executorMemory && cpus >= 1 && if (totalCoresAcquired < maxCores && mem >= executorMemory && cpus >= 1 &&
failuresBySlaveId.getOrElse(slaveId, 0) < MAX_SLAVE_FAILURES &&
!slaveIdsWithExecutors.contains(slaveId)) { !slaveIdsWithExecutors.contains(slaveId)) {
// Launch an executor on the slave // Launch an executor on the slave
val cpusToUse = math.min(cpus, maxCores - totalCoresAcquired) val cpusToUse = math.min(cpus, maxCores - totalCoresAcquired)
val taskId = newMesosTaskId() val taskId = newMesosTaskId()
taskIdToSlaveId(taskId) = slaveId
slaveIdsWithExecutors += slaveId
coresByTaskId(taskId) = cpusToUse
val task = MesosTaskInfo.newBuilder() val task = MesosTaskInfo.newBuilder()
.setTaskId(TaskID.newBuilder().setValue(taskId.toString).build()) .setTaskId(TaskID.newBuilder().setValue(taskId.toString).build())
.setSlaveId(offer.getSlaveId) .setSlaveId(offer.getSlaveId)
...@@ -210,15 +219,27 @@ class CoarseMesosSchedulerBackend( ...@@ -210,15 +219,27 @@ class CoarseMesosSchedulerBackend(
override def statusUpdate(d: SchedulerDriver, status: TaskStatus) { override def statusUpdate(d: SchedulerDriver, status: TaskStatus) {
val taskId = status.getTaskId.getValue.toInt val taskId = status.getTaskId.getValue.toInt
logInfo("Mesos task " + taskId + " is now " + status.getState) val state = status.getState
logInfo("Mesos task " + taskId + " is now " + state)
synchronized { synchronized {
if (isFinished(status.getState)) { if (isFinished(state)) {
val slaveId = taskIdToSlaveId(taskId)
slaveIdsWithExecutors -= slaveId
taskIdToSlaveId -= taskId
// Remove the cores we have remembered for this task, if it's in the hashmap // Remove the cores we have remembered for this task, if it's in the hashmap
for (cores <- coresByTaskId.get(taskId)) { for (cores <- coresByTaskId.get(taskId)) {
totalCoresAcquired -= cores totalCoresAcquired -= cores
coresByTaskId -= taskId coresByTaskId -= taskId
driver.reviveOffers() // In case we'd rejected everything before but have now lost a node
} }
// If it was a failure, mark the slave as failed for blacklisting purposes
if (state == MesosTaskState.TASK_FAILED || state == MesosTaskState.TASK_LOST) {
failuresBySlaveId(slaveId) = failuresBySlaveId.getOrElse(slaveId, 0) + 1
if (failuresBySlaveId(slaveId) >= MAX_SLAVE_FAILURES) {
logInfo("Blacklisting Mesos slave " + slaveId + " due to too many failures; " +
"is Spark installed on it?")
}
}
driver.reviveOffers() // In case we'd rejected everything before but have now lost a node
} }
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment