Spark入门——2:spark运行模式及原理

一:spark的运行模式
       spark的运行模式有多种。当部署在单机上的时候,可以用本地模式(local),或者伪分布式模式;当以分布式集群的方式部署时,也有多种运行模式:
     1,spark内建的Standalone模式:Spark:hostname:port  
     2,本地模式,使用N核:Local[N]
3,伪分布式:Local cluster[workernum,core,Memory]
     4,Mesos模式:Mesos://hostname:port
     5,YARN模式一:YARN standalone/YARN cluster 。主程序的逻辑和任务都运行在YARN集群中
     6,YARN模式二:YARN Client。主逻辑程序运行在本地,具体任务运行在YARN集群中
二:spark的术语:
     1,Application:基于Spark的应用,包含了driver程序
2,Driver Program:运行main函数并且新建SparkContext的程序(通过SparkContext可以连接到不同的Cluster Manager上)
3,Cluster Manager:是在集群上获取资源的一个外部服务(例如:Standalone,Mesos,Yarn)。对于一个SparkContext而言,用哪种ClusterManager是没有关系的,它的最终目的是获得Executor。
4,Worker Node:集群中可以运行应用代码的节点
5,Executor:在一个worker node上为某个应用启动的一个进程,该进程负责运行任务,并且负责将数据存在内存或者磁盘上,每个应用都有自己独立的excutors
6,Task:被送到某个executor上的工作单元(每个partition一定会分配一个task)
7,Job:包含很多任务的并行计算,可以看做和Spark的action对应
8,Stage:一个Job被拆分成很多组任务,每组任务被称为Stage(就像Mapreduce分map任务和reduce任务)
三:spark的工作流程:
    虽然spark的部署模式多种多样,但是其工作流程大致相同。总体来说,都是将spark的人应用分为任务调度和任务执行。所有的spark应用程序都离不开SparkContext和Executor两部分,
SparkContext作为程序运行的唯一入口,通过资源调度模块,和Executor通信。如下图所示:


    
具体的说,在SparkContext的初始化过程中,Spark会分别创建DAGScheduler作业调度和TaskScheduler任务调度两级调度模块。
DAGScheduler为每个作业计算具有依赖关系的多个调度阶段(通常根据shuffle来划分),然后为每一个阶段构建出一组具体的任务(通常考虑数据本地性),然后以TaskSets的形式提交给
TaskScheduler来具体执行。
TaskScheduler的主要职责是:1,具体启动任务;2,监控,汇报任务运行情况。
作业调度模块和具体的部署运行环境无关,然而,不同模式下的任务调度模块还是有区别的。不同的运行模式根据底层资源调度方式的不同,各自实现了自己的任务调度模块。
四,相关基础类:
        1,TaskScheduler/SchedulerBackend
所有的运行模式实现的任务调度,都是基于TaskScheduler和SchedulerBackend这两个接口(Trait)。如下TaskScheduler接口的源码:

        


private[spark] trait TaskScheduler {
//生成任务ID
private val appId = "spark-application-" + System.currentTimeMillis
def rootPool: Pool
def schedulingMode: SchedulingMode
def start(): Unit
def postStartHook() { }

// 和cluster断开连接.
def stop(): Unit

// 提交一个待运行的任务集.
def submitTasks(taskSet: TaskSet): Unit

// 取消一个调度阶段的所有任务.
def cancelTasks(stageId: Int, interruptThread: Boolean)

// 设置DAG scheduler用来回调相关函数. 它必须是在submitTasks被调用之前被设定.
def setDAGScheduler(dagScheduler: DAGScheduler): Unit

// 默认的并行度,作为决定作业并行度的一个参数.
def defaultParallelism(): Int
//让master知道BlockManager是活着的
def executorHeartbeatReceived(execId: String, taskMetrics: Array[(Long, TaskMetrics)],
blockManagerId: BlockManagerId): Boolean

def applicationId(): String = appId

} 

TaskScheduler的主要任务是和DAGScheduler交互,负责任务的的具体调度和执行。核心接口是submitTasks和cancelTasks 。


如下所示是SchedulerBackend的源码:

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
  

SchedulerBackend的核心接口是reviveOffers()。SchedulerBackend的作用是与底层资源调度系统相交互。配合TaskScheduler实现具体任务执行所需要的资源 。


TaskSchedulerImpl实现了TaskScheduler的接口,提供了很多任务调度的接口。另外为Backend提供了resourceOffers和statusUpdate用于调度资源和更新任务状态。当TaskSchedulerImpl发起任务资源调度请求时,是通过调用Backend的receiveOffers函数。


最后就是任务的执行,实际上任务的运行都是交给Executor类来执行,它会给每一个Task都创建一个TaskRunner,然后交到线程池中去运行。ExecutorBackend最终会将运行结果返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值