CoarseGrainedSchedulerBackend是Driver端用到的,CoarseGrainedExecutorBackend是Executor端用到的。他们都是Backend,什么是Backend?Backend其实就是负责端到端通信的,这两个CoarseGrained的Backend是负责Driver和Executor之间的通信的。
什么是Driver呢?Driver就是我们编写的spark代码,里面的main函数就是Driver跑的代码。
什么是Executor呢?Executor就是执行spark的Task任务的地方,Backend接收到Driver的LaunchTask消息后,调用Executor类的launchTask方法来执行任务。
Driver会启动CoarseGrainedSchedulerBackend,通过CoarseGrainedSchedulerBackend来向集群申请机器以便启动Executor,会找到一台机器,发送命令让机器启动一个ExecutorRunner,ExecutorRunner里启动CoarseGrainedExecutorBackend向Driver注册,并创建Executor来处理CoarseGrainedExecutorBackend接收到的请求。刚刚说的是Standalone部署下的流程,Yarn下大部分类似,只有向集群申请机器来启动Executor这一步不太一样,这个简单说一下吧。
Yarn环境下,是通过spark-yarn工程里的几个类一级yarn本身的功能来一起完成机器的部署和分区任务的分发。
spark-yarn包含两个文件:client.java和ApplicationMaster.java。
client.java功能是向yarn申请资源来执行ApplicationMaster.java的代码,所以这里主要看下ApplicationMaster.java的代码功能是什么。
ApplicationMaster首先干两件事,启动一个"/bin/mesos-master"和多个"/bin/mesos-slave",这都是向yarn申请资源然后部署上去执行的,都是yarn的功能部分,"/bin/mesos-master"和"/bin/mesos-slave"是yarn环境里自带的两个bin程序,可以看成是类似Standalone环境下的Master和Worker。
launchContainer方法是启动yarn的container,也就是前面说的在container上启动“/bin/mesos-slave",mesos-slave会向mesos-master注册的。等需要的slave节点资源全部申请启动完成后,调用startApplication()方法开始执行Driver。
startApplication()方法:
// Start the user's application
private void startApplication() throws IOException {
try {
String sparkClasspath = getSparkClasspath();
String jobJar = new File("job.jar").getAbsolutePath();
String javaArgs = "-Xms" + (masterMem - 128) + "m -Xmx" + (masterMem - 128) + "m";
javaArgs += " -Djava.library.path=" + mesosHome + "/lib/java";
String substitutedArgs = programArgs.replaceAll("\\[MASTER\\]", masterUrl);
if (mainClass.equals("")) {
javaArgs += " -cp " + sparkClasspath + " -jar " + jobJar + " " + substitutedArgs;
} else {
javaArgs += " -cp " + sparkClasspath + ":" + jobJar + " " + mainClass + " " + substitutedArgs;
}
String java = "java";
if (System.getenv("JAVA_HOME") != null) {
java = System.getenv("JAVA_HOME") + "/bin/java";
}
String bashCommand = java + " " + javaArgs +
" 1>" + logDirectory + "/application.stdout" +
" 2>" + logDirectory + "/application.stderr";
LOG.info("Command: " + bashCommand);
String[] command = new String[] {"bash", "-c", bashCommand};
String[] env = new String[] {"SPARK_HOME=" + sparkHome, "MASTER=" + masterUrl,
"SPARK_MEM=" + (slaveMem - 128) + "m"};
application = Runtime.getRuntime().exec(command, env);
new Thread("wait for user application") {
public void run() {
try {
appExitCode = application.waitFor();
appExited = true;
LOG.info("User application exited with code " + appExitCode);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
} catch (SparkClasspathException e) {
unregister(false);
System.exit(1);
return;
}
}
这就是启动Driver了,masterUrl就是”bin/mesos-master“的地址,设置成了环境变量”MASTER“来用了。