Spark運行模式有Local,STANDALONE,YARN,MESOS,KUBERNETES這5種,其中最為常見的是YARN運行模式,它又可分為Client模式和Cluster模式。這里以Spark自帶的SparkPi來說明這些運行模式。
本文作為第一篇,先結合SparkPi程序來說明Yarn Client方式的流程。
以下是Spark中examples下的SparkPi程序。
1 // scalastyle:off println 2 package org.apache.spark.examples 3 4 import scala.math.random 5 6 import org.apache.spark.sql.SparkSession 7 8 /** Computes an approximation to pi */ 9 object SparkPi { 10 def main(args: Array[String]) { 11 val spark = SparkSession 12 .builder 13 .appName("Spark Pi") 14 .getOrCreate() 15 val slices = if (args.length > 0) args(0).toInt else 2 16 val n = math.min(100000L * slices, Int.MaxValue).toInt // avoid overflow 17 val count = spark.sparkContext.parallelize(1 until n, slices).map { i => 18 val x = random * 2 - 1 19 val y = random * 2 - 1 20 if (x*x + y*y <= 1) 1 else 0 21 }.reduce(_ + _) 22 println(s"Pi is roughly ${4.0 * count / (n - 1)}") 23 spark.stop() 24 } 25 } 26 // scalastyle:on println
這個是Spark用於計算圓周率PI的scala程序,思想很簡單,就是利用以坐標軸原點為中心畫一個邊長為2的正方形,原點距離正方形的上下左右邊距離均為1,然后再以原點為中心畫一個半徑為1的圓,此時正方形的面積是4,圓的面積是PI,上面程序所做的就是在正方形里隨機取若干個點(比如上面程序默認的20萬),計算有多少個點落在圓形里面,那么可以認為這個等式是成立的,即:“圓面積” / “正方形面積” = “落在圓內的點數” / “正方形內的點數”,也就是,PI / 4 = count / (n-1),所以PI = 4 * count / (n-1)。
Spark程序可以分為Driver部分和Executor部分,Driver可以認為是程序的master部分,具體而言1~16行和22~25行都是Driver部分,其余的17~21行是Executor部分,即執行具體邏輯計算的部分,上面程序slices默認是2,也就是說,默認會有2個Task來執行計算。
下面來以yarn client方式來執行這個程序,注意執行程序前先要啟動hdfs和yarn,最好同時啟動spark的history server,這樣即使在程序運行完以后也可以從Web UI中查看到程序運行情況。
輸入以下命令:
[root@BruceCentOS4 spark]# $SPARK_HOME/bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode client $SPARK_HOME/examples/jars/spark-examples_2.11-2.3.0.jar
以下是程序運行輸出信息部分截圖,
開始部分:

中間部分:

結束部分:

由於程序是以yarn client方式運行的,因此Driver是運行在客戶端的(BruceCentOS4上的SparkSubmit進程),同時在BruceCentOS和BruceCentOS3上各運行了1個Executor進程(進程名字:CoarseGrainedExecutorBackend),另外在BruceCentOS上還有1個名字為ExecutorLauncher的進程,這個進程主要是作為Yarn程序中的ApplicationMaster,因為Driver運行在客戶端,它僅僅作為ApplicationMaster為運行Executor向ResourceManager申請資源。
SparkUI上的Executor信息:

BruceCentOS4上的客戶端進程(包含Spark Driver):

BruceCentOS上的ApplicationMaster和Executor:

BruceCentOS3上的Executor:

下面具體描述下Spark程序在yarn client模式下運行的具體流程。
這里是一個流程圖:

- Spark Yarn Client向YARN的ResourceManager申請啟動ApplicationMaster。同時在SparkContent初始化中將創建DAGScheduler和TASKScheduler等,由於我們選擇的是Yarn-Client模式,程序會選擇YarnClientSchedulerBackend。
- ResourceManager收到請求后,在集群中選擇一個NodeManager,為該應用程序分配第一個Container,要求它在這個Container中啟動應用程序的ApplicationMaster,對應進程名字是ExecutorLauncher。與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申請注銷並關閉自己。
以上就是個人對Spark運行模式(yarn client)的一點理解,其中參考了“求知若渴 虛心若愚”博主的“Spark(一): 基本架構及原理”的部分內容(其中基於Spark2.3.0對某些細節進行了修正),在此表示感謝。
