軟件版本
* spark 2.0.2
* 2.6.0-cdh5.9.0
一.編譯
參考官網配置即可:
http://spark.apache.org/docs/latest/running-on-yarn.html
下載spark2.0.2的源碼後在根目錄進行編譯
dev/make-distribution.sh \
-Phive -Phive-thriftserver \
-Dhadoop.version=2.6.0-cdh5.9.0 \
-Dyarn.version=2.6.0-cdh5.9.0 \
--tgz -Pyarn
可能需要配置倉庫
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
二.配置
在yarn上運行spark需要在spark-env.sh
或環境變量中配置HADOOP_CONF_DIR
或YARN_CONF_DIR
目錄指向hadoop的配置文件。
spark-default.conf
中配置spark.yarn.jars
指向hdfs上的spark需要的jar包。如果不配置該參數,每次啓動spark程序將會將driver端的SPARK_HOME
打包上傳分發到各個節點。
spark.yarn.jars hdfs://clusterName/spark/spark2/jars/*
啓動spark程序時,其他節點會自動去下載這些包並進行緩存,下次啓動如果包沒有變化則會直接讀取本地緩存的包。
緩存清理間隔在yarn-site.xml
通過yarn.nodemanager.localizer.cache.cleanip.interval-ms
配置
啓動spark-shell,指定master爲yarn,默認爲client模式:
/usr/install/spark2/bin/spark-shell
--master yarn
--deploy-mode client
--executor-memory 1g
--executor-cores 1
--driver-memory 1g
--queue test (默認隊列是default)
Dynamic allocation
動態申請/釋放executor可以提高集羣資源利用率。適用於spark-shell
這種交互或長時任務等場景。
在spark-default.conf
中配置
spark.dynamicAllocation.enabled true
spark.shuffle.service.enabled true
spark.dynamicAllocation.minExecutors 0
spark.dynamicAllocation.maxExecutors 20
External Shuffle Service
在yarn-site.xml中修改參數(如果是使用cdh,在 yarn-site.xml
的 YARN 服務高級配置代碼段
中添加xml片段,重啓nodeManager即可。)
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle,spark_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.spark_shuffle.class</name>
<value>org.apache.spark.network.yarn.YarnShuffleService</value>
</property>
<property>
<name>spark.shuffle.service.port</name>
<value>7338</value>
</property>
tip: 爲了減少shuffle service的gc帶來的性能影響,可以提高NodeManager的內存,默認只有1G。
如果沒有成功開啓External shuffle service,提交任務將會報錯。
Caused by: java.io.IOException: Failed to send RPC 7920194824462016141 to /172.27.1.63:41034: java.nio.channels.ClosedChannelException
shuffle文件目錄
Spark shuffle等臨時文件寫入目錄的設置
cluster mode
spark.local.dirs
路徑被yarn.nodemanager.local-dirs
取代,shuffle文件將會寫入到yarn配置的目錄下。
client mode
driver 沒有在container中啓動,因此依舊使用spark.local.dirs
配置,executor在container中啓動,使用的是yarn.nodemanager.local-dirs
的配置。
在nodeManager的日誌中可以看到,blockmgr已經寫入yarn.nodemanager.local-dirs
所配置的目錄
ExternalShuffleBlockResolver
Registered executor AppExecId{appId=application_1486360553595_0003, execId=5} with ExecutorShuffleInfo{localDirs=[/data/yarn/nm/usercache/admin/appcache/application_1486360553595_0003/blockmgr-0ae6c816-fb68-4614-9a3c-1e8620e45d4d, /data1/yarn/nm/usercache/admin/appcache/application_1486360553595_0003/blockmgr-af95ae92-4f69-46ba-9bd7-216595b852a8, subDirsPerLocalDir=64, shuffleManager=org.apache.spark.shuffle.sort.SortShuffleManager}
三.調度
Fair Scheduler
CDH默認使用Fair Scheduler,Fair Scheduler將會盡量嘗試每個任務均勻分配資源,同時也支持隊列。
- 在A隊列中提交job1,獨佔集羣資源運行。
- 在B隊列中提交job2,job1在隊列B中的資源被回收,提供給job2。
- 在B隊列中提交job3,job2和job3共享隊列B的資源
tip: 上訴所說的僅僅是一種理想情況,實際上在spark on yarn模式中,如果container沒有釋放,後續的其他任務依舊是申請不到資源的。這也是爲什麼要使用dynamic allocation的一個原因。
隊列設置
隊列可以設置資源分配的比例,每個隊列資源的最大最小值等。
具體可以參考cloudera:
https://www.cloudera.com/documentation/enterprise/5-5-x/topics/cm_mc_resource_pools.html
資源搶佔(Preempt)
如同上面說的,如果A隊列的job1同時佔用了B隊列的資源,那麼此時在B隊列提交的job2可能得不到資源而處於等待狀態(job1的container沒釋放)。
可以通過資源搶佔的方式,通過殺死job1的 container釋放資源,使job2可以獲得隊列B的資源正常執行。
這種方式將會犧牲集羣資源,因爲被殺死的container需要被重新計算。
yarn-site.xml中設置
* yarn.scheduler.fair.preemption
- 通過參數控制是否開啓搶佔,默認爲false
yarn.scheduler.fair.preemption.cluster-utilization-threshold
- 默認爲0.8f,意味着最多可以搶佔到集羣所有資源的80%
fair-scheduler.xml中設置
* defaultMinSharePreemptionTimeout
設置一個隊列等待多長時間開始搶佔
delay scheduling
延時調度是爲了提高數據本地性而設置。
每一個 node manager 會定期發送心跳給 resource manager,這其中就包含了該 node manager 正在運行的 container 數量以及可以分配給新 container 的資源。當採用延遲調度策略時,調度器並不會立即使用收集到的信息,而會等待一段時間,以達到遵從 locality 的目的。
yarn.scheduler.fair.locality.threshold.node
和yarn.scheduler.fair.locality.threshold.rack
參數配置0-1之間的浮點數,如果設置爲0.1則表示等待超過10%的節點發送心跳信息後再分配container。默認爲-1表示不進行延時調度。
hadoop2.6 FairScheduler文檔
http://hadoop.apache.org/docs/r2.6.0/hadoop-yarn/hadoop-yarn-site/FairScheduler.html