1 spark on yarn常用屬性介紹
屬性名 | 默認值 | 屬性說明 |
---|---|---|
spark.yarn.am.memory |
512m | 在客戶端模式(client mode )下,yarn 應用master 使用的內存數。在集群模式(cluster mode )下,使用spark.driver.memory 代替。 |
spark.driver.cores |
1 | 在集群模式(cluster mode )下,driver 程序使用的核數。在集群模式(cluster mode )下,driver 程序和master 運行在同一個jvm 中,所以master 控制這個核數。在客戶端模式(client mode )下,使用spark.yarn.am.cores 控制master 使用的核。 |
spark.yarn.am.cores |
1 | 在客戶端模式(client mode )下,yarn 應用的master 使用的核數。在集群模式下,使用spark.driver.cores 代替。 |
spark.yarn.am.waitTime |
100ms | 在集群模式(cluster mode)下,yarn 應用master 等待SparkContext 初始化的時間。在客戶端模式(client mode )下,master 等待driver 連接到它的時間。 |
spark.yarn.submit.file.replication |
3 | 文件上傳到hdfs 上去的replication 次數 |
spark.yarn.preserve.staging.files |
false |
設置為true 時,在job 結束時,保留staged 文件;否則刪掉這些文件。 |
spark.yarn.scheduler.heartbeat.interval-ms |
3000 |
Spark 應用master 與yarn resourcemanager 之間的心跳間隔 |
spark.yarn.scheduler.initial-allocation.interval |
200ms | 當存在掛起的容器分配請求時,spark 應用master 發送心跳給resourcemanager 的間隔時間。它的大小不能大于spark.yarn.scheduler.heartbeat.interval-ms ,如果掛起的請求還存在,那么這個時間加倍,直到到達spark.yarn.scheduler.heartbeat.interval-ms 大小。 |
spark.yarn.max.executor.failures |
numExecutors * 2 ,并且不小于3 |
在失敗應用程序之前,executor 失敗的最大次數。 |
spark.executor.instances |
2 |
Executors 的個數。這個配置和spark.dynamicAllocation.enabled 不兼容。當同時配置這兩個配置時,動態分配關閉,spark.executor.instances 被使用 |
spark.yarn.executor.memoryOverhead |
executorMemory * 0.10 ,并且不小于384m
|
每個executor 分配的堆外內存。 |
spark.yarn.driver.memoryOverhead |
driverMemory * 0.10 ,并且不小于384m
|
在集群模式下,每個driver 分配的堆外內存。 |
spark.yarn.am.memoryOverhead |
AM memory * 0.10 ,并且不小于384m
|
在客戶端模式下,每個driver 分配的堆外內存 |
spark.yarn.am.port |
隨機 |
Yarn 應用master 監聽的端口。 |
spark.yarn.queue |
default |
應用提交的yarn 隊列的名稱 |
spark.yarn.jar |
none |
Jar 文件存放的地方。默認情況下,spark jar 安裝在本地,但是jar 也可以放在hdfs 上,其他機器也可以共享。 |
2 客戶端模式和集群模式的區別
這里我們要區分一下什么是客戶端模式(client mode
),什么是集群模式(cluster mode
)。
我們知道,當在YARN
上運行Spark
作業時,每個Spark executor
作為一個YARN
容器(container
)運行。Spark
可以使得多個Tasks
在同一個容器(container
)里面運行。 yarn-cluster
和yarn-client
模式的區別其實就是Application Master
進程的區別,在yarn-cluster
模式下,driver
運行在AM
(Application Master
)中,它負責向YARN
申請資源,并監督作業的運行狀況。當用戶提交了作業之后,就可以關掉Client
,作業會繼續在YARN
上運行。然而yarn-cluster
模式不適合運行交互類型的作業。 在yarn-client
模式下,Application Master
僅僅向YARN
請求executor
,client
會和請求的container
通信來調度他們工作,也就是說Client
不能離開。下面的圖形象表示了兩者的區別。


2.1 Spark on YARN集群模式分析
2.1.1 客戶端操作
- 1、根據
yarnConf
來初始化yarnClient
,并啟動yarnClient
; - 2、創建客戶端
Application
,并獲取Application
的ID
,進一步判斷集群中的資源是否滿足executor
和ApplicationMaster
申請的資源,如果不滿足則拋出IllegalArgumentException
; - 3、設置資源、環境變量:其中包括了設置
Application
的Staging
目錄、準備本地資源(jar
文件、log4j.properties
)、設置Application
其中的環境變量、創建Container
啟動的Context
等; - 4、設置
Application
提交的Context
,包括設置應用的名字、隊列、AM
的申請的Container
、標記該作業的類型為Spark
; - 5、申請
Memory
,并最終通過yarnClient.submitApplication
向ResourceManager
提交該Application
。
當作業提交到YARN
上之后,客戶端就沒事了,甚至在終端關掉那個進程也沒事,因為整個作業運行在YARN
集群上進行,運行的結果將會保存到HDFS
或者日志中。
2.1.2 提交到YARN集群,YARN操作
- 1、運行
ApplicationMaster
的run
方法; - 2、設置好相關的環境變量。
- 3、創建
amClient
,并啟動; - 4、在
Spark UI
啟動之前設置Spark UI
的AmIpFilter
; - 5、在
startUserClass
函數專門啟動了一個線程(名稱為Driver
的線程)來啟動用戶提交的Application
,也就是啟動了Driver
。在Driver
中將會初始化SparkContext
; - 6、等待
SparkContext
初始化完成,最多等待spark.yarn.applicationMaster.waitTries
次數(默認為10),如果等待了的次數超過了配置的,程序將會退出;否則用SparkContext
初始化yarnAllocator
; - 7、當
SparkContext、Driver
初始化完成的時候,通過amClient
向ResourceManager
注冊ApplicationMaster
; - 8、分配并啟動
Executeors
。在啟動Executeors
之前,先要通過yarnAllocator
獲取到numExecutors
個Container
,然后在Container
中啟動Executeors
。 如果在啟動Executeors
的過程中失敗的次數達到了maxNumExecutorFailures
的次數,maxNumExecutorFailures
的計算規則如下:
// Default to numExecutors * 2, with minimum of 3
private val maxNumExecutorFailures = sparkConf.getInt("spark.yarn.max.executor.failures",
sparkConf.getInt("spark.yarn.max.worker.failures", math.max(args.numExecutors * 2, 3)))
那么這個Application
將失敗,將Application Status
標明為FAILED
,并將關閉SparkContext
。其實,啟動Executeors
是通過ExecutorRunnable
實現的,而ExecutorRunnable
內部是啟動CoarseGrainedExecutorBackend
的。
- 9、最后,
Task
將在CoarseGrainedExecutorBackend
里面運行,然后運行狀況會通過Akka
通知CoarseGrainedScheduler
,直到作業運行完成。
2.2 Spark on YARN客戶端模式分析
和yarn-cluster
模式一樣,整個程序也是通過spark-submit
腳本提交的。但是yarn-client
作業程序的運行不需要通過Client
類來封裝啟動,而是直接通過反射機制調用作業的main
函數。下面是流程。
- 1、通過
SparkSubmit
類的launch
的函數直接調用作業的main
函數(通過反射機制實現),如果是集群模式就會調用Client
的main
函數。 - 2、而應用程序的
main
函數一定都有個SparkContent
,并對其進行初始化; - 3、在
SparkContent
初始化中將會依次做如下的事情:設置相關的配置、注冊MapOutputTracker、BlockManagerMaster、BlockManager
,創建taskScheduler
和dagScheduler
; - 4、初始化完
taskScheduler
后,將創建dagScheduler
,然后通過taskScheduler.start()
啟動taskScheduler
,而在taskScheduler
啟動的過程中也會調用SchedulerBackend
的start
方法。 在SchedulerBackend
啟動的過程中將會初始化一些參數,封裝在ClientArguments
中,并將封裝好的ClientArguments
傳進Client
類中,并client.runApp()
方法獲取Application ID
。 - 5、
client.runApp
里面的做的和上章客戶端進行操作那節類似,不同的是在里面啟動是ExecutorLauncher
(yarn-cluster
模式啟動的是ApplicationMaster
)。 - 6、在
ExecutorLauncher
里面會初始化并啟動amClient
,然后向ApplicationMaster
注冊該Application
。注冊完之后將會等待driver
的啟動,當driver
啟動完之后,會創建一個MonitorActor
對象用于和CoarseGrainedSchedulerBackend
進行通信(只有事件AddWebUIFilter
他們之間才通信,Task
的運行狀況不是通過它和CoarseGrainedSchedulerBackend
通信的)。 然后就是設置addAmIpFilter
,當作業完成的時候,ExecutorLauncher
將通過amClient
設置Application
的狀態為FinalApplicationStatus.SUCCEEDED
。 - 7、分配
Executors
,這里面的分配邏輯和yarn-cluster
里面類似。 - 8、最后,
Task
將在CoarseGrainedExecutorBackend
里面運行,然后運行狀況會通過Akka
通知CoarseGrainedScheduler
,直到作業運行完成。 - 9、在作業運行的時候,
YarnClientSchedulerBackend
會每隔1秒通過client
獲取到作業的運行狀況,并打印出相應的運行信息,當Application
的狀態是FINISHED、FAILED
和KILLED
中的一種,那么程序將退出等待。 - 10、最后有個線程會再次確認
Application
的狀態,當Application
的狀態是FINISHED、FAILED
和KILLED
中的一種,程序就運行完成,并停止SparkContext
。整個過程就結束了。
3 spark submit 和 spark shell參數介紹
參數名 | 格式 | 參數說明 |
---|---|---|
--master | MASTER_URL | 如spark://host:port |
--deploy-mode | DEPLOY_MODE | Client或者master,默認是client |
--class | CLASS_NAME | 應用程序的主類 |
--name | NAME | 應用程序的名稱 |
--jars | JARS | 逗號分隔的本地jar包,包含在driver和executor的classpath下 |
--packages | 包含在driver和executor的classpath下的jar包逗號分隔的”groupId:artifactId:version”列表 | |
--exclude-packages | 用逗號分隔的”groupId:artifactId”列表 | |
--repositories | 逗號分隔的遠程倉庫 | |
--py-files | PY_FILES | 逗號分隔的”.zip”,”.egg”或者“.py”文件,這些文件放在python app的PYTHONPATH下面 |
--files | FILES | 逗號分隔的文件,這些文件放在每個executor的工作目錄下面 |
--conf | PROP=VALUE | 固定的spark配置屬性 |
--properties-file | FILE | 加載額外屬性的文件 |
--driver-memory | MEM | Driver內存,默認1G |
--driver-java-options | 傳給driver的額外的Java選項 | |
--driver-library-path | 傳給driver的額外的庫路徑 | |
--driver-class-path | 傳給driver的額外的類路徑 | |
--executor-memory | MEM | 每個executor的內存,默認是1G |
--proxy-user | NAME | 模擬提交應用程序的用戶 |
--driver-cores | NUM | Driver的核數,默認是1。這個參數僅僅在standalone集群deploy模式下使用 |
--supervise | Driver失敗時,重啟driver。在mesos或者standalone下使用 | |
--verbose | 打印debug信息 | |
--total-executor-cores | NUM | 所有executor總共的核數。僅僅在mesos或者standalone下使用 |
--executor-core | NUM | 每個executor的核數。在yarn或者standalone下使用 |
--driver-cores | NUM | Driver的核數,默認是1。在yarn集群模式下使用 |
--queue | QUEUE_NAME | 隊列名稱。在yarn下使用 |
--num-executors | NUM | 啟動的executor數量。默認為2。在yarn下使用 |
你可以通過spark-submit --help
或者spark-shell --help
來查看這些參數。
參考文獻
【1】Spark:Yarn-cluster和Yarn-client區別與聯系