Spark開發-Spark執行模式及原理一
核心
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執行原理和RDDSpark
- Spark的執行原理Spark
- spark執行原理、模型Spark模型
- 【Spark】 Spark作業執行原理--獲取執行結果Spark
- Spark原理-物理執行圖Spark
- Spark學習(一)——執行模式與執行流程Spark模式
- Spark開發-Local模式Spark模式
- Spark開發-Standalone模式Spark模式
- spark基礎之spark sql執行原理和架構SparkSQL架構
- Spark on Yarn 部分一原理及使用SparkYarn
- Spark開發-Yarn cluster模式SparkYarn模式
- Spark修煉之道(進階篇)——Spark入門到精通:第七節 Spark執行原理Spark
- Spark 以及 spark streaming 核心原理及實踐Spark
- Spark開發-執行架構基本概念Spark架構
- 本地開發spark程式碼上傳spark叢集服務並執行(基於spark官網文件)Spark
- Spark資料收藏--------Spark執行架構Spark架構
- Spark開發-Spark核心細說Spark
- Spark開發-spark環境搭建Spark
- spark學習筆記--叢集執行SparkSpark筆記
- spark-stage任務劃分、sparkclient執行模式Sparkclient模式
- 大資料開發-Spark Join原理詳解大資料Spark
- 《深入理解Spark》之Spark的整體執行流程Spark
- 檢視spark程式執行狀態以及安裝sparkSpark
- Spark Task 的執行流程② - 建立、分發 TaskSpark
- Spark面試題(七)——Spark程式開發調優Spark面試題
- Hadoop 及Spark 分散式HA執行環境搭建HadoopSpark分散式
- spark streaming原始碼分析3 排程及執行Spark原始碼
- Spark開發-SparkSql的開發SparkSQL
- Spark開發-控制操作Spark
- Spark開發-transformations操作SparkORM
- Spark開發-Action操作Spark
- Spark 從零到開發(五)初識Spark SQLSparkSQL
- Spark的工作原理Spark
- Spark2 jar包執行完成,退出spark,釋放資源SparkJAR
- spark sql語句效能最佳化及執行計劃SparkSQL
- Spark導論(Spark自學一)Spark
- Spark叢集和任務執行Spark
- spark job執行引數優化Spark優化