Spark運行模式有Local,STANDALONE,YARN,MESOS,KUBERNETES這5種,其中最為常見的是YARN運行模式,它又可分為Client模式和Cluster模式。這裡以Spark自帶的SparkPi來說明這些運行模式。 本文作為第一篇,先結合SparkPi程式來說明Yarn ...
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對某些細節進行了修正),在此表示感謝。