Spark开发-Spark运行模式及原理一
来源:互联网 发布:网络推广部职能 编辑:程序博客网 时间:2024/06/07 04:44
核心
1、介绍Spark的运行模块有哪几种
2、TaskScheduler和TaskSchedulerBackend介绍
3、Executor介绍
spark的运行模式多种多样,灵活多变,部署在单机上时,既可以用本地模式运行,也可以用伪分布模式运行,而当以分布式集群的方式部署时,也有众多的运行模式可以供选择,这取决于集群的实际情况,底层的资源调度既可以依赖于外部的资源调度框架,也可以使用spark内建的standalone模式,对于外部资源调度框架的支持,目前支持mesos和yarn
1、spark运行模式概述
1、1spark运行模式列表
在实际应用中,spark应用程序的运行模式取决于传递给SparkContext的MASTER环境变量的值,个别模式还需要依赖辅助的程序接口来配合使用,目前所有支持的MASTER环境变量由特定的字符串或URL所组成。
Lcoal[N]:本地模式,使用N个线程
Local cluster[worker,core,Memory]:伪分布式模式,可以配置所需要启动的虚拟工作节点数量,以及每个工作节点所管理的CPU数量和内存大小
Spark://Hostname:port : standalone模式,需要部署spark到相关节点,URL为spark Master主机地址和端口
Mesos://hostname:port : mesos模式,需要部署spark和Mesos到相关节点,URL为Mesos主机地址和端口
YARN Standalone/YARN cluster: YARN模式一:主程序逻辑和任务都运行在YARN集群中
YARN Client: YARN 模式二:主程序逻辑运行在本地,具体任务运行在YARN集群中
1、2spark基本工作流程
看到这么多运行模式,其实内部的工作流程很相似,他们从根本上都是将Spark的应用分为任务调度和任务执行两个部分,下图是分布式模式下,Spark的各个调度和执行模块的大致框架图,对于本地模式来说,其内部程序逻辑结构也是类似的,只是其中部分模块有所简化,例如集群管理模块简化为进程内部的线程池。
下图可以看到,所有的spark应用程序都离不开SparkContext和Executor两部分,Executor负责执行任务,运行Executor的机器称为worker节点,SparkContext由用户程序启动,通过资源调度模块和Executor通信,SparkContext和Executor这两部分的核心代码实现在各种运行模式中都是公用的,在它们之上,根据运行部署模式的不同,包装了不同调度模块以及相关的适配代码。
具体来说,以SparkContext为程序运行的入口,在SparkContext的初始化过程中,Spark会分别创建DAGScheduler作业调度和TaskScheduler任务调度两级调度模块。
其中作业调度模块是基于任务阶段的高层调度模块,它为每个spark作业计算具有依赖关系的多个调度阶段(通常根据shuffle来划分),然后为每个阶段构建出一组具体的任务(通常会考虑数据的本地性等),然后以TaskSets(任务组)的形式提交给任务调度模块来具体执行。而任务调度器则负责具体任务启动、监控和汇报任务运行情况。
作业调度模块和具体的部署运行模块无关,在各种运行模式下逻辑相同,
不同运行模式的区别主要体现在任务调度模块,不同的部署和 运行模式,根据底层资源调度方式的不同,各自实现了自己特定的任务调度模块,用来将任务实际调度给对应的计算资源。
1、3 相关基本类
TaskScheduler和SchedulerBackend
为了抽象一个公共的接口给DAGScheduler作业调度模块使用,所有的这些运行模式实现的任务调度模块都是基于这两个接口(Trait)的,TaskScheduler和SchedulerBackend
TaskScheduler程序
private[spark] trait TaskScheduler {//设置application的ID值 private val appId = "spark-application-" + System.currentTimeMillis def rootPool: Pool def schedulingMode: SchedulingMode def start(): Unit def postStartHook() { } def stop(): Unit//提交待运行的任务集 def submitTasks(taskSet: TaskSet): Unit//取消一个调度阶段的所有任务 def cancelTasks(stageId: Int, interruptThread: Boolean)//设置 DAG Scheduler 用来回调相关函数 def setDAGScheduler(dagScheduler: DAGScheduler): Unit//默认的并行度,作为决定作业并行度的一个参数 def defaultParallelism(): Int def executorHeartbeatReceived(execId: String, taskMetrics: Array[(Long, TaskMetrics)], blockManagerId: BlockManagerId): Boolean def applicationId(): String = appId//处理失去丢失的executor def executorLost(executorId: String, reason: ExecutorLossReason): Unit def applicationAttemptId(): Option[String]}
TaskScheduler的实现主要用于与DAGScheduler交互,负责任务的具体调度和运行,其核心接口是submitTasks和cancelTasks
private[spark] trait SchedulerBackend { private val appId = "spark-application-" + System.currentTimeMillis def start(): Unit def stop(): Unit def reviveOffers(): Unit def defaultParallelism(): Int def killTask(taskId: Long, executorId: String, interruptThread: Boolean): Unit = throw new UnsupportedOperationException def isReady(): Boolean = true def applicationId(): String = appId def applicationAttemptId(): Option[String] = None def getDriverLogUrls: Option[Map[String, String]] = None}
SchedulerBackend的实现是与底层资源调度系统交互(如mesos和yarn),配合TaskScheduler实现具体任务执行所需要的资源分配,核心接口是reviveOffers
这两者之间的实际交互过程取决于具体字段调度模式,理论上这两者的实现的成对匹配工作的,之所以拆分成2部分,是有利于相似的调度模式共享代码功能模式,
TaskSchedulerImpl
TaskSchedulerImpl实现了TaskScheduler接口,提供了大多数本地和分布式运行调度模式的任务调度接口
private[spark] class TaskSchedulerImpl( val sc: SparkContext, val maxTaskFailures: Int, isLocal: Boolean = false) extends TaskScheduler with Logging
此外它还实现了resourceOffers和statusUpdate这两个接口供Backend调用,用于提供调度资源和更新任务状态。
def resourceOffers(offers: Seq[WorkerOffer]): Seq[Seq[TaskDescription]]def statusUpdate(tid: Long, state: TaskState, serializedData: ByteBuffer)
另外,在提交任务和更新状态等阶段,TaskSchedulerImp1都会调用Backend的reviveOffers函数,用于发起一次任务资源调度请求。
Executor
实际任务的运行,最终都由Executor类来执行,Executor对每一个任务创建一个TaskRunner类,交给线程池运行,
代码如下
//启动线程池private val threadPool = ThreadUtils.newDaemonCachedThreadPool("Executor task launch worker")//运行任务列表private val runningTasks = new ConcurrentHashMap[Long, TaskRunner]def launchTask( context: ExecutorBackend, taskId: Long, attemptNumber: Int, taskName: String, serializedTask: ByteBuffer): Unit = { val tr = new TaskRunner(context, taskId = taskId, attemptNumber = attemptNumber, taskName, serializedTask) runningTasks.put(taskId, tr) threadPool.execute(tr)}运行的结果最终通过ExecutorBackend接口返回private[spark] trait ExecutorBackend { def statusUpdate(taskId: Long, state: TaskState, data: ByteBuffer)}
- Spark开发-Spark运行模式及原理一
- Spark运行模式及原理(一)
- Spark入门——2:spark运行模式及原理
- Spark实践项目3:Spark运行模式及原理
- Spark开发-spark运行原理和RDD
- Spark的运行模式及运行命令
- spark 调优及运行原理
- spark-07-spark 运行模式
- Spark(一): 基本架构及原理
- Spark(一): 基本架构及原理
- Spark(一): 基本架构及原理
- Spark(一): 基本架构及原理
- IntelliJ Idea开发spark程序及运行
- Spark运行原理
- Spark作业运行原理
- Spark运行原理
- Spark 任务运行原理
- spark 运行原理
- 【模板】并查集 两种路径压缩写法
- 数组的遍历并按标准格式输出
- 【算法】二分图的判定
- 进程间通讯——无名管道
- 【算法】Bellman-Ford算法(单源最短路径问题)(判断负圈)
- Spark开发-Spark运行模式及原理一
- 网页实时聊天之PHP实现websocket
- 【算法】Dijkstra算法(单源最短路径问题) 邻接矩阵和邻接表实现
- 10.22
- 如何绑定hosts文件?怎么将IP地址与域名绑定?
- HibernateUtils.java
- 使用PowerDesigner绘制类图
- 2017 Fall SoftwareEngineering Learning (5)
- 链表排序,链表冒泡排序(算法非原创)