1. 什么是 Apache Spark?
Apache Spark是一种开放源代码并行处理框架,支持使用内存中处理来提升大数据分析应用程序的性能。 大数据解决方案旨在处理对传统数据库来说太大或太复杂的数据。 Spark 处理内存中的大量数据,这比基于磁盘的替代方法要快得多。Spark可在 YARN、Apache Mesos、Kubernetes 上运行,也可独立或在云端运行。借助用于 SQL、流处理、机器学习和图形处理的高级运算符及库,Spark 使开发者能够通过交互式 shell、笔记本或应用程序包来使用 Scala、Python、R 或 SQL 轻松构建并行应用程序。通过功能编程模型和相关查询引擎 Catalyst,Spark 支持批量和交互式分析,可将作业转换为查询方案,并跨集群节点调度查询方案中的操作。Spark 核心数据处理引擎之上存在多个用于 SQL 和 DataFrame、机器学习、GraphX、图形计算和流处理的库。用户可在来自各种数据源(例如 HDFS、Alluxio、Apache Cassandra、Apache HBase 或 Apache Hive)的海量数据集上结合使用这些库。
2 Spark的四大特性
2.1 Simple(易用性)
Spark 提供了丰富的高级运算操作,支持丰富的算子,并支持 Java、Python、Scala、R、SQL 等语言的 API,使用户可以快速构建不同的应用。
开发人员只需调用 Spark 封装好的 API 来实现即可,无需关注 Spark 的底层架构。
2.2 Fast(速度快)
Spark 将处理的每个任务都构造成一个DAG(Directed Acyclic Graph, 有向无环图)来执行,实现原理是基于RDD(Resilient Distributed Dataset, 弹性分布式数据集)在内存中对数据进行迭代计算,以实现批量和流式数据的高性能快速计算处理。
Spark比MR速度快的原因:
- 基于内存
mapreduce任务后期再计算的时候,每一个job的输出结果会落地到磁盘,后续有其他的job需要依赖于前面job的输出结果,这个时候就需要进行大量的磁盘io操作。性能就比较低。spark任务后期再计算的时候,job的输出结果可以保存在内存中,后续有其他的job需要依赖于前面job的输出结果,这个时候就直接从内存中获取得到,避免了磁盘io操作,性能比较高.
对于spark程序和mapreduce程序都会产生shuffle阶段,在shuffle阶段中它们产生的数据都会落地到磁盘。 - 进程与线程
mapreduce任务以进程的方式运行在Yarn集群中,比如程序中有100个MapTask,一个task就需要一个进程,这些task要运行就需要开启100个进程。
spark任务以线程的方式运行在进程中,比如程序中有100个MapTask,后期一个task就对应一个线程,这里就不再是进程,这些task需要运行,这里可以极端一点:只需要开启1个进程,在这个进程中启动100个线程就可以了。进程中可以启动很多个线程,而开启一个进程与开启一个线程需要的时间和调度代价是不一样。 开启一个进程需要的时间远远大于开启一个线程。## Scalable(可融合性)
2.3 Unified(通用性)
大数据处理的传统方案需要维护多个平台,比如,离线任务是放在 Hadoop MapRedue 上运行,实时流计算任务是放在 Storm 上运行。而Spark 提供了一站式的统一解决方案,可用于批处理、交互式查询(Spark SQL)、实时流处理(Spark Streaming)、机器学习(Spark MLlib)和图计算(GraphX)等。这些不同类型的处理都可以在同一个应用中无缝组合使用。
2.4 Scalable(兼容性)
Spark可以非常方便地与其他的开源产品进行融合。比如,Spark可以使用Hadoop的YARN和Apache Mesos作为它的资源管理和调度器,并且可以处理所有Hadoop支持的数据,包括HDFS、HBase和Cassandra等。这对于已经部署Hadoop集群的用户特别重要,因为不需要做任何数据迁移就可以使用Spark的强大处理能力。Spark也可以不依赖于第三方的资源管理和调度器,它实现了Standalone作为其内置的资源管理和调度框架,这样进一步降低了Spark的使用门槛,使得所有人都可以非常容易地部署和使用Spark。此外,Spark还提供了在EC2上部署Standalone的Spark集群的工具。
3.集群管理类型
3.1 Standalone
Standalone是Spark自带的资源管理器,如果一个集群是Standalone的话,那么就需要在多台机器上同时部署spark环境,只要修改一台机器配置,就要同步到所有的机器上去,比较麻烦,生产环境中不采取。
3.2 Apache Mesos
官方推荐这种模式(原因之一是血缘关系)。正是由于Spark开发之初就考虑到支持Mesos,因此,目前而言,Spark运行在Mesos上会比运行在YARN上更加灵活,更加自然。用户可选择两种调度模式之一运行自己的应用程序:
3.1.1 粗粒度模式(Coarse-grained Mode):
每个应用程序的运行环境由一个Dirver和若干个Executor组成,其中,每个Executor占用若干资源,内部可运行多个Task(对应多少个“slot”)。应用程序的各个任务正式运行之前,需要将运行环境中的资源全部申请好,且运行过程中要一直占用这些资源,即使不用,最后程序运行结束后,回收这些资源。
3.1.2 细粒度模式(Fine-grained Mode):
鉴于粗粒度模式会造成大量资源浪费,Spark On Mesos还提供了另外一种调度模式:细粒度模式,这种模式类似于现在的云计算,思想是按需分配.。
3.3 Hadoop YARN
Spark on Yarn 模式就是将Spark应用程序跑在Yarn集群之上,通过Yarn资源调度将executor启动在container中,从而完成driver端分发给executor的各个任务。将Spark作业跑在Yarn上,首先需要启动Yarn集群,然后通过spark-shell或spark-submit的方式将作业提交到Yarn上运行。
2.4 Kubernetes
Spark官方2.4版本,通过ExternalManger的方式,加入了对kubernetes任务和资源调度的功能,且功能相对稳定,但整个集群的部署和用户作业的提交更加偏向于Spark传统的部署和提交方式,这对于熟悉Kubernetes用户而不是很熟悉Spark的用户,或是相反的用户来说,在技术栈上存在一差异,因此同样是Google的团队,开源了Spark Operator项目,从Kubernetes的视角封装了Spark on Kubertes的功能,有兴趣的同学可以深入了解。
2.5 Local
Local模式就是运行在一台计算机上的模式,通常就是用于在本机上练手和测试,不推荐在生产环境中使用。
4.Spark On Yarn
Spark 可以跑在很多集群上,比如跑在local上,跑在Standalone上,跑在Apache Mesos上,跑在Hadoop YARN上等等。不管你Spark跑在什么上面,它的代码都是一样的,区别只是–master的时候不一样。其中Spark on YARN是工作中或生产上用的非常多的一种运行模式。
4.1Yarn产生背景
以前没有Yarn的时候,每个分布式框架都要跑在一个集群上面,比如说Hadoop要跑在一个集群上,Spark用集群的时候跑在standalone上,MPI要跑在一个集群上面,等等。
而且每个分布式框架在各自的集群上跑的时候,都有高峰期低峰期的时候,每个时间点也可能不一样。
这样的话整个集群的资源的利用率非常的低。而且管理起来比较麻烦,因为每个框架都跑在各自的集群上,要去分别管理。
那么能不能进行统一的资源管理和调度?这样Yarn就产生了。
4.2 什么是Yarn
Yarn 是分布式资源管理框架,相当于分布式的操作系统,会有程序运行在上面。
涉及到以下几个角色:
RM:resource manager 资源管理者。全局只有一个,统一管理集群资源。
NM:node mananger 节点管理者。分布在每一个节点,向RM汇报节点的信息。
Yarn分配资源都是以container作为资源的分配单位,Yarn的应用程序都会被装到container中去运行。每个节点可能有很多个大小不一的container都有NM控制并向RM汇报。
Yarn 上运行的程序涉及到的角色(每个Yarn程序都需要有的):
AC: application client 。负责提交任务到Yarn,监控程序运行状态。可以在不属于Yarn管理的集群中的机器上运行。
AW: application worker。分布在Yarn各个container中去执行具体的工作。
AM: application master 应用程序管理者。负责和NM交付申请container分配任务,收集结果。
4.3 Spark 结构
4.3.1 Cluster Manager
Cluster Manager 是 Spark 的集群资源管理器,存在于 Master 进程中,主要用于对整个集群资源进行管理和分配,根据其部署模式的不同,可以分为 Local、Standalone、YARN、Mesos、Cloud 等模式。
4.3.2 Driver:
执行客户端写好的main方法,它会构建一个名叫SparkContext对象,该对象是所有spark程序的执行入口。
4.3.3 Worker:
Spark的工作节点,用于执行提交的任务,其主要的工作职责有以下几点:
Worker 节点通过注册机向 Cluster Manager 汇报自身的 CPU、内存等资源使用信息。
Worker 节点在 Spark Master 的指示下,创建并启用 Executor(真正的计算单元)。
Spark Master 将资源和 Task 分配给 Worker 节点上的 Executor 并执行运用。
Worker 节点同步 Executor 状态和资源信息给 Cluster Manager。
4.3.4 Executor:
它是一个进程,它会在worker节点启动该进程(计算资源),一个worker节点可以有多个Executor进程
4.3.5 Task:
spark任务是以task线程的方式运行在worker节点对应的executor进程中
4.3.6 Application:
Application 是基于 Spark API 编写的应用程序,包括实现 Driver 功能的代码和在集群中各个 Executor 上要执行的代码。
一个 Application 由多个 Jobs 组成。
其中 Application 的入口为用户所定义的 main() 方法。
4.4 Spark Yarn Client 模式
- Spark Yarn Client向YARN的ResourceManager申请启动Application Master。同时在SparkContent初始化中将创建DAGScheduler和TASKScheduler等,由于我们选择的是Yarn-Client模式,程序会选择YarnClientClusterScheduler和YarnClientSchedulerBackend;
- ResourceManager收到请求后,在集群中选择一个NodeManager,为该应用程序分配第一个Container,要求它在这个Container中启动应用程序的ApplicationMaster,与YARN-Cluster区别的是在该ApplicationMaster不运行SparkContext,只与SparkContext进行联系进行资源的分派;
- Client中的SparkContext初始化完毕后,与ApplicationMaster建立通讯,向ResourceManager注册,根据任务信息向ResourceManager申请资源(Container);
- 一旦ApplicationMaster申请到资源(也就是Container)后,便与对应的NodeManager通信,要求它在获得的Container中启动启动CoarseGrainedExecutorBackend,CoarseGrainedExecutorBackend启动后会向Client中的SparkContext注册并申请Task;
- Client中的SparkContext分配Task给CoarseGrainedExecutorBackend执行,CoarseGrainedExecutorBackend运行Task并向Driver汇报运行的状态和进度,以让Client随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务;
- 应用程序运行完成后,Client的SparkContext向ResourceManager申请注销并关闭自己。
4.4 Spark Yarn cluster 模式
-
Spark Yarn Client向YARN中提交应用程序,包括ApplicationMaster程序、启动ApplicationMaster的命令、需要在Executor中运行的程序等;
-
ResourceManager收到请求后,在集群中选择一个NodeManager,为该应用程序分配第一个Container,要求它在这个Container中启动应用程序的ApplicationMaster,其中ApplicationMaster进行SparkContext等的初始化;
-
ApplicationMaster向ResourceManager注册,这样用户可以直接通过ResourceManage查看应用程序的运行状态,然后它将采用轮询的方式通过RPC协议为各个任务申请资源,并监控它们的运行状态直到运行结束;
-
一旦ApplicationMaster申请到资源(也就是Container)后,便与对应的NodeManager通信,要求它在获得的Container中启动启动CoarseGrainedExecutorBackend,CoarseGrainedExecutorBackend启动后会向ApplicationMaster中的SparkContext注册并申请Task。这一点和Standalone模式一样,只不过SparkContext在Spark Application中初始化时,使用CoarseGrainedSchedulerBackend配合YarnClusterScheduler进行任务的调度,其中YarnClusterScheduler只是对TaskSchedulerImpl的一个简单包装,增加了对Executor的等待逻辑等;
-
ApplicationMaster中的SparkContext分配Task给CoarseGrainedExecutorBackend执行,CoarseGrainedExecutorBackend运行Task并向ApplicationMaster汇报运行的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务;
-
应用程序运行完成后,ApplicationMaster向ResourceManager申请注销并关闭自己。
综上
- Yarn cluster: 这个就是生产环境常用的模式,所有的资源调度和计算都在集群环境上运行。
- Yarn client: 这个是说Spark Driver和ApplicationMaster进程均在本机运行,而计算任务在cluster上。
这里我们会更倾向于Yarn cluster
5.用例演示
不同的环境环境配置不同,这里只简单演示下Windows下的
1.配置hadoop环境
官网下载hadoop-3.3.4.tar.gz,解压后设置环境变量
HADOOP_HOME=D``:``\hadoop\hadoop-3.3.4``HADOOP_COMMON_LIB_NATIVE_DIR=D``:``\hadoop\hadoop-3.3.4\lib\native``HADOOP_OPTS="-Djava.library.path=D``:``\hadoop\hadoop-3.3.4\lib" |
|---|
2.配置spark客户端环境
官网下载spark-3.3.1-bin-hadoop3.tgz,解压后设置环境变量
SPARK_HOME=D``:``\hadoop\spark-3.3.1-bin-hadoop3 |
|---|
3.提交java应用
这里采用SparkLauncher来提交SparkJar,而SparkLauncher也有两种方式提交:
- new SparkLauncher().launch() 直接启动一个Process,效果跟以前一样
- new SparkLauncher().startApplicaiton(监听器) 返回一个SparkAppHandler,并(可选)传入一个监听器
当然是更倾向于第二种,因为好处很多:
- 自带输出重定向(Output,Error都有,支持写到文件里面),超级爽的功能
- 可以自定义监听器,当信息或者状态变更时,都能进行操作(对我没啥用)
- 返回的SparkAppHandler支持 暂停、停止、断连、获得AppId、获得State等多种功能。