spark-22.spark内核解析_2_Spark的脚本

1.集群管理脚本

start-all.sh
调用 start-master.sh CLASS=”org.spark.deploy.master.Master” 执行main(),并传入一些参数。
调用 start-slave.sh CLASS=”org.spark.deploy.worker.Worker” 执行main(),并传入一些参数。
stop-all.sh 类似。

2.任务提交脚本

spark-submit.sh
spark-class.sh org.apache.spark.deploy.SparkSubmit 执行该类的main,传入jar包相关参数。

spark-shell.sh
调用 spark-submit.sh
spark-class.sh org.apache.spark.deploy.SparkSubmit 传入的启动类 org.apache.spark.repl.Main

3.StandAlone集群的启动

StandAlone集群的启动

  1. Master启动时首先创一个RpcEnv对象,负责管理所有通信逻辑。
  2. Master通过RpcEnv对象创建一个Endpoint,Master就是一个Endpoint,Worker可以与其进行通信。
  3. Worker启动时也是创一个RpcEnv对象。
  4. Worker通过RpcEnv对象创建一个Endpoint。
  5. Worker通过RpcEnv对象,建立到Master的连接,获取到一个RpcEndpointRef对象,通过该对象可以与Master通信。
  6. Worker向Master注册,注册内容包括主机名、端口、CPU Core数量、内存数量。
  7. Master接收到Worker的注册,将注册信息维护在内存中的Table中,其中还包含了一个到Worker的RpcEndpointRef对象引用。
  8. Master回复Worker已经接收到注册,告知Worker已经注册成功。
  9. 此时如果有用户提交Spark程序,Master需要协调启动Driver;而Worker端接收到成功注册响应后,开始周期性向Master发送心跳。

4.应用提交与运行过程

上图中,通过不同颜色或类型的线条,给出了如下6个核心的交互流程,我们会详细说明:

橙色:提交用户Spark程序

用户提交一个Spark程序,主要的流程如下所示:

  1. 用户执行spark-submit脚本提交一个Spark程序,会创建一个ClientEndpoint对象,该对象负责与Master通信交互。
  2. ClientEndpoint向Master发送一个RequestSubmitDriver消息,表示提交用户程序。
  3. Master收到RequestSubmitDriver消息,向ClientEndpoint回复。SubmitDriverResponse,表示用户程序已经完成注册。
  4. ClientEndpoint向Master发送RequestDriverStatus消息,请求Driver状态
  5. 如果当前用户程序对应的Driver已经启动,则ClientEndpoint直接退出,完成提交用户程序。

紫色:启动Driver进程

当用户提交用户Spark程序后,需要启动Driver来处理用户程序的计算逻辑,完成计算任务,这时Master协调需要启动一个Driver,具体流程如下所示:

  1. Maser内存中维护着用户提交计算的任务Application,每次内存结构变更都会触发调度,向Worker发送LaunchDriver请求
  2. Worker收到LaunchDriver消息,会启动一个DriverRunner线程去执行LaunchDriver的任务
  3. DriverRunner线程在Worker上启动一个新的JVM实例,该JVM实例内运行一个Driver进程,该Driver会创建SparkContext对象

红色:注册Application

Dirver启动以后,它会创建SparkContext对象,初始化计算过程中必需的基本组件,并向Master注册Application,流程描述如下:

  1. 创建SparkEnv对象,创建并管理一些基本组件
  2. 创建TaskScheduler,负责Task调度
  3. 创建StandaloneSchedulerBackend,负责与ClusterManager进行资源协商
  4. 创建DriverEndpoint,其它组件可以与Driver进行通信
  5. 在StandaloneSchedulerBackend内部创建一个StandaloneAppClient,负责处理与Master的通信交互
  6. StandaloneAppClient创建一个ClientEndpoint,实际负责与Master通信
  7. ClientEndpoint向Master发送RegisterApplication消息,注册Application
  8. Master收到RegisterApplication请求后,回复ClientEndpoint一个RegisteredApplication消息,表示已经注册成功

蓝色:启动Executor进程

  1. Master向Worker发送LaunchExecutor消息,请求启动Executor;同时Master会向Driver发送ExecutorAdded消息,表示Master已经新增了一个Executor(此时还未启动)
  2. Worker收到LaunchExecutor消息,会启动一个ExecutorRunner线程去执行LaunchExecutor的任务
  3. Worker向Master发送ExecutorStageChanged消息,通知Executor状态已发生变化
  4. Master向Driver发送ExecutorUpdated消息,此时Executor已经启动

粉色:启动Task执行

  1. StandaloneSchedulerBackend启动一个DriverEndpoint
  2. DriverEndpoint启动后,会周期性地检查Driver维护的Executor的状态,如果有空闲的Executor便会调度任务执行
  3. DriverEndpoint向TaskScheduler发送Resource Offer请求
  4. 如果有可用资源启动Task,则DriverEndpoint向Executor发送LaunchTask请求
  5. Executor进程内部的CoarseGrainedExecutorBackend调用内部的Executor线程的launchTask方法启动Task
  6. Executor线程内部维护一个线程池,创建一个TaskRunner线程并提交到线程池执行

绿色:Task运行完成

  1. Executor进程内部的Executor线程通知CoarseGrainedExecutorBackend,Task运行完成
  2. CoarseGrainedExecutorBackend向DriverEndpoint发送StatusUpdated消息,通知Driver运行的Task状态发生变更
  3. StandaloneSchedulerBackend调用TaskScheduler的updateStatus方法更新Task状态
  4. StandaloneSchedulerBackend继续调用TaskScheduler的resourceOffers方法,调度其他任务运行

5.spark任务的划分

在这里插入图片描述
在这里插入图片描述

1、Application

用户编写的Spark程序,完成一个计算任务的处理。它是由一个Driver程序和一组运行于Spark集群上的Executor组成。

2、Job

用户程序中,每次调用Action时,逻辑上会生成一个Job,一个Job包含了多个Stage。

3、Stage

Stage包括两类:ShuffleMapStage和ResultStage,如果用户程序中调用了需要进行Shuffle计算的Operator,如groupByKey等,就会以Shuffle为边界分成ShuffleMapStage和ResultStage。

4、TaskSet

基于Stage可以直接映射为TaskSet,一个TaskSet封装了一次需要运算的、具有相同处理逻辑的Task,这些Task可以并行计算,粗粒度的调度是以TaskSet为单位的。

5、Task

Task是在物理节点上运行的基本单位,Task包含两类:ShuffleMapTask和ResultTask,分别对应于Stage中ShuffleMapStage和ResultStage中的一个执行基本单元。

6.Shuffle过程

1.mapreduce-shuffle

在这里插入图片描述
Shuffle横跨Map端和Reduce端,在Map端包括Spill、Merge过程,在Reduce端包括copy和sort、reduce过程。
在这里插入图片描述
Map任务会不断的以(k,v)形式将数据写入到环形缓冲区kvbuffer,在写的过程中,同时记录kvmeta,写入索引信息。
在这里插入图片描述
在这里插入图片描述
kvmeta的记录和(k,v)数据的记录,是从kvbuffer中对着头写,一般当写道剩余空间还有20%的时候启动sortAndSpillt线程。这个时候要注意,如果Map再有数据写入,kvmeta和(k,v)的写入起始位置会发生改变。split线程启动后,会根据partition和key在kvmeta里面排好序。然后线程启动写文件过程,产生一个索引文件(如果内存不足)和一个数据文件。
在这里插入图片描述
reduce端就会从各个map的httpserver上考取自己的partition数据,拷贝回来的数据都是有序的,多个map相同partition的数据进行排序,一边排序一边进行数据的合并,最后合并成一个大文件。

2.Spark-HashShufle

在这里插入图片描述

Map任务会为每个Reduce创建对应的bucket,Map产生的结果会根据设置的Partitioner得到对应的bucketId,然后填充到相应的bucket中去。每个Map的输出结果可能包含所有的Reduce所需要的数据,所以每个Map会创建R个bucket(R是reduce的个数),M个Map总共会创建M*R个bucket。 然后bucket缓冲区中的数据就写入到以文件名hash值为名的blockfile中,Reduce从远端或者本地逐个读取自己需要的文件,放到一个大的Hashmap中,key是Map输出的key,Map输出对应这个key的所有value组成HashMap的value,如果内存不够就溢写到磁盘。 缺点:大量小文件的读写问题。
SPARK的Shuffle过程 – HashShuffle改进:
在这里插入图片描述
这种方式的改进是减少了map端的磁盘文件数量,map在某个节点上第一次执行,为每个reduce创建bucket对应的输出文件,把这些文件组织成ShuffleFileGroup,当这次map执行完之后,这个ShuffleFileGroup可以释放为下次循环利用;当又有map在这个节点上执行时,不需要创建新的bucket文件,而是在上次的ShuffleFileGroup中取得已经创建的文件继续追加写一个segment;当前次map还没执行完,ShuffleFileGroup还没有释放,这时如果有新的map在这个节点上执行,无法循环利用这个ShuffleFileGroup,而是只能创建新的bucket文件组成新的ShuffleFileGroup来写输出。reduce过程与第一阶段相同。

3. spark Shuffle-SortShuffle

在这里插入图片描述
实现逻辑类似于Hadoop MapReduce,Hash Shuffle每一个reducers产生一个文件,但是Sort Shuffle只是产生一个按照reducer id排序可索引的文件,也就是一个数据文件和一个索引文件。
数据文件中的数据按照Reducer排序,但属于同一个Reducer的数据不排序。Mapper产生的数据先放到AppendOnlyMap这个数据结构中,如果内存不够,数据则会spill到磁盘,最后合并成一个文件。reduce端进行远程或者本地读取进行合并。
需要注意的一点是对于reducer数比较少的情况,Hash Shuffle明显要比Sort Shuffle快,因此Sort Shuffle有个“fallback”计划,对于reducers数少于 “spark.shuffle.sort.bypassMergeThreshold” (200 by default),我们使用fallback计划,hashing相关数据到分开的文件,然后合并这些文件为一个。

7.内存管理

堆内内存:Executor 的内存管理建立在 JVM 的内存管理之上。–executor-memory 指定Executor内存。并不能准确记录实际可用的堆内内存。
堆外内存:Spark 引入了堆外(Off-heap)内存,利用 JDK Unsafe API进行实现。存储序列化后的二进制数据。通过配置 spark.memory.offHeap.enabled 参数启用,并由 spark.memory.offHeap.size 参数设定堆外空间的大小 在这里插入图片描述

1.堆内内存-静态内存

在这里插入图片描述

2. 堆内内存-统一内存

在这里插入图片描述

3.堆外内存-静态

在这里插入图片描述

4.堆外内存-统一

在这里插入图片描述

5.动态占用

在这里插入图片描述
设定基本的存储内存和执行内存区域(spark.storage.storageFraction 参数),该设定确定了双方各自拥有的空间的范围。 双方的空间都不足时,则存储到硬盘;若己方空间不足而对方空余时,可借用对方的空间;(存储空间不足是指不足以放下一个完整的 Block)。执行内存的空间被对方占用后,可让对方将占用的部分转存到硬盘,然后"归还"借用的空间。
存储内存的空间被对方占用后,无法让对方“归还”,只有等待结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值