spark 的运行模式

Spark多种运行模式

整理自:https://www.jianshu.com/p/65a3476757a5

刚接触Spark时,很希望能对它的运行方式有个直观的了解,而Spark同时支持多种运行模式,官网和书籍中对他们的区别所说不详,尤其是模式之间是否有关联、启动的JVM进程是否有区别、启动的JVM进程的作用是否都一样,等等这些都没有说明,也没有现成的资料可以查询。所以,我今天总结一下,供新手参考和学习(下述结论基于 Spark 2.1.0 版本和 Hadoop 2.7.3 版本)

测试或实验性质的本地运行模式 (单机)

该模式被称为 Local[N] 模式,是用单机的多个线程来模拟Spark 分布式计算,通常用来验证开发出来的应用程序逻辑上有没有问题。

其中 N 代表可以使用 N 个线程,每个线程拥有一个core。如果不指定 N ,则默认是 1 个线程(该线程有 1 个core)。如果是 local[*],则代表 Run Spark locally with as many worker threads as logical cores on your machine.

如下:

spark-submit 和 spark-submit –master local 效果是一样的,(同理:spark-shell 和 spark-shell –master local 效果是一样的)。
spark-submit –master local[4] 代表会有 4 个线程(每个线程一个core)来并发执行应用程序。

那么,这些线程都运行在什么进程下呢?后面会说到,请接着往下看。

运行该模式非常简单,只需要把 Spark 的安装包解压后,改一些常用的配置即可使用,而不用启动 Spark 的 Master、Worker 守护进程(只有集群的Standalone方式时,才需要这两个角色),也不用启动 Hadoop 的各服务(除非你要用到 HDFS ),这是和其他模式的区别,要记住才能理解。

那么,这些执行任务的线程,到底是共享在什么进程中呢?我们用如下命令提交作业:

1
spark-submit --class JavaWordCount --master local[10] JavaWordCount.jar file:///tmp/test.txt

可以看到,在程序执行过程中,只会生成一个 SparkSubmit 进程。

这个 SparkSubmit 进程又当爹、又当妈,既是客户提交任务的Client 进程、又是 Spark 的 driver 程序、还充当着 Spark 执行 Task 的 Executor角色

这里有个小插曲,因为 Driver 程序在应用程序结束后就会终止,那么如何在 web 界面看到该应用程序的执行情况呢,需要如此这般:

  1. 先在 spark-env.sh 增加 SPARK_HISTORY_OPTS;
  2. 然后启动 start-history-server.sh 服务;
  3. 就可以看到启动了 HistoryServer 进程,且监听端口是 18080。
  4. 之后就可以在 web 上使用 http://hostname:18080 愉快的玩耍了。

想必你们已经清楚了第一种运行模式了吧,我们接着往下说。

2,测试或实验性质的本地伪集群运行模式(单机模拟集群)

这种运行模式,和 Local[N] 很像,不同的是,它会在单机启动多个进程来模拟集群下的分布式场景,而不像 Local[N] 这种多个线程只能在一个进程下委屈求全的共享资源。通常也是用来验证开发出来的应用程序逻辑上有没有问题,或者想使用 Spark 的计算框架而没有太多资源。

用法是:提交应用程序时使用 local-cluster[x, y, z]。

参数:

  • x 代表要生成的 executor 数
  • y 代表每个 executor 所拥有的 core 数
  • z 代表每个 executor 所拥有的 memory 数
1
2
spark-submit --master local-cluster[2, 3, 1024]
spark-shell --master local-cluster[2, 3, 1024]

上面这条命令代表会使用 2 个 executor 进程,每个进程分配 3 个 core 和 1G 的内存来运行应用程序。可以看到,在程序执行过程中,会生成如下几个进程:

SparkSubmit 依然充当全能角色,又是 Client 进程,又是Driver 程序,还有点资源管理的作用。生成的两个 CoarseGrainedExecutorBackend 就是用来并发执行程序的进程。它们使用的资源如下:

运行该模式依然非常简单,只需要把 Spark 的安装包解压后,改一些常用的配置即可使用。而不用启动 Spark 的 Master、Worker 守护进程(只有集群的 standalone 方式时,才需要这两个角色),也不用启动 Hadoop 的各服务(除非你要用到HDFS),这一点倒是和 local[N] 完全一样。

Spark 自带 Cluster Manager 的 Standalone Client 模式(集群)

终于说到了体现分布式计算价值的地方了!(有了前面的基础,后面的内容我会稍微说快一点,只讲本文的关注点)

和单机运行的模式不同,这里必须在执行应用程序前,先启动Spark 的 Master 和 Worker 守护进程。不用启动 Hadoop 服务,除非你用到了 HDFS 的内容。

1
2
start-master.sh
start-slave.sh -h hostname url:master

如果图省事,可以用start-all.sh一条命令即可,不过这样做,和上面的分开执行有点差别,以后讲到数据本地性如何验证时会说。

启动的进程如下:(其他非 Master 节点上只会有 Worker 进程)

这种运行模式,可以使用 Spark 的 8080 web ui 来观察资源和应用程序的执行情况了。

可以看到,当前环境下,我启动了 8 个 worker 进程,每个可使用的 core 是 2 个,内存没有限制。

言归正传,用如下命令提交应用程序

1
2
spark-submit --master spark://wl1:7077
spark-submit --master spark://wl1:7077 --deploy-mode client

代表着会在所有有 Worker 进程的节点上启动 Executor 来执行应用程序,此时产生的 JVM 进程如下:(非 master 节点,除了没有 Master、SparkSubmit,其他进程都一样)

  • Master 进程作为 cluster manager,用来对应用程序申请的资源进行管理;
  • SparkSubmit 作为 Client 端和运行 driver 程序;
  • CoarseGrainedExecutorBackend 用来并发执行应用程序;

注意,Worker 进程生成几个 Executor,每个 Executor 使用几个 core,这些都可以在 spark-env.sh 里面配置,此处不再啰嗦。

Spark 自带 cluster manager 的 standalone cluster 模式(集群)

这种运行模式也是需要先启动 spark 的 Master、Worker 守护进程),不用启动 Hadoop 服务,除非你用到了HDFS的内容。使用如下命令执行应用程序:

1
spark-submit --master spark://wl1:6066 --deploy-mode cluster

各节点启动的进程情况如下:

  • master 节点上的进程

  • 提交应用程序的客户端上的进程

  • 某 worker 节点上的进程

这种模式和上面说的第三种还是有很大差别的,包括:

  1. 客户端的 SparkSubmit 进程会在应用程序提交给集群之后就退出
  2. Master 会在集群中选择一个 Worker 进程生成一个子进程DriverWrapper 来启动 Driver程序
  3. 而 DriverWrapper 进程会占用 Worker 进程的一个 core,所以同样的资源下配置下,会比第 3 种运行模式,少用 1 个 core 来参与计算(观察下图 executor id 7 的 core数

  1. 应用程序的结果,会在执行 driver 程序的节点(某 Worker)的 stdout 中输出,而不是打印在屏幕上

基于 YARN 的 Resource Manager 的 Client 模式(集群)

现在越来越多的场景,都是 Spark 跑在 Hadoop 集群中,所以为了做到资源能够均衡调度,会使用 YARN 来做为 Spark 的 Cluster Manager,来为 Spark 的应用程序分配资源。

在执行 Spark 应用程序前,要启动 Hadoop 的各种服务。由于已经有了资源管理器,所以不需要启动 Spark 的 Master、Worker 守护进程。相关配置的修改,请自行研究。

使用如下命令执行应用程序:

1
2
spark-submit --master yarn 
spark-submit --master yarn --deploy-mode client

提交应用程序后,各节点会启动相关的进程如下:

  • 在 Resource Manager 节点上提交应用程序,会生成 SparkSubmit 进程,该进程会执行 driver 程序;
  • RM会在集群中的某个 NodeManager 上,启动一个ExecutorLauncher 进程,来做为 ApplicationMaster;
  • 会在多个 NodeManager 上生成 CoarseGrainedExecutorBackend 进程来并发的执行应用程序。

对应的 YARN 资源管理的单元 Container,关系如下:

为 ApplicationMaster 生成了容器 000001;
为 CoarseGrainedExecutorBackend 生成了容器 000002-000003。

基于YARN的Resource Manager的Custer模式(集群)

使用如下命令执行应用程序:

1
spark-submit --master yarn --deploy-mode cluster

和第 5 种运行模式,区别如下:

  1. 在 Resource Manager 端提交应用程序,会生成SparkSubmit 进程,该进程只用来做 Client 端,应用程序提交给集群后,就会删除该进程;
  2. Resource Manager 在集群中的某个 NodeManager 上运行 ApplicationMaster,该 AM 同时会执行 driver 程序。紧接着,会在各 NodeManager 上运行 CoarseGrainedExecutorBackend 来并发执行应用程序。
  3. 应用程序的结果,会在执行 driver 程序的节点的 stdout 中输出,而不是打印在屏幕上。

当然,3-6 这几种运行模式,你也可以在一台单机上玩,前提是你的服务器足够牛。

总结

这六种模式可以分为三组:

  • 1、2 组都是单机模式,区别是 1 只有一个进程,承担了所有角色,2 会有两类多个进程,有独立的执行器进程;
  • 3、4 组是集群模式,都是用 Spark 自带的 Master 和 Worker 来管理资源,区别是 3(client)的提交任务的节点承担 Driver 的角色,任务不执行完它不退出,4(cluster)中提交任务的节点在提完了之后进程会退出,Spark 在执行器节点中选择一个承担 Driver 角色;
  • 5、6 组也是集群模式,与 3、4 的区别是使用 YARN 来管理资源,然后 5(client)、6(cluster)与 3、4 的关系类似。