集群配置
-
软件配置
- Hadoop 2.6.0
- Spark 2.2.0
-
硬件配置
- 三台服务器,32 核 64G 500G
- 总资源:32 核 64G x 3 = 48核 192G
- Yarn 可分配总资源:48 核 60G x 3 = 144核180G
默认情况下,yarn 可分配核 = 机器核 x 1.5,yarn 可分配内存 = 机器内存 x 0.8。
提交作业:
直接使用了 Spark 官方的 example 包,所以不需要自己上传 jar 包。参数列表如下所示:
--class org.apache.spark.examples.SparkPi --master yarn --deploy-mode client --driver-memory 4g --num-executors 2 --executor-memory 2g --executor-cores 2 /opt/apps/spark-1.6.0-bin-hadoop2.6/lib/spark-examples*.jar 10
参数说明如下:
资源计算:
在不同模式、不同的设置下运行时,作业使用的资源情况如下表所示:
-
yarn-client 模式的资源计算
- 作业主程序(Driver 程序)会在 master 节点上执行。按照作业配置将分配 4G(由 —driver-memroy 指定)的内存给它(当然实际上可能没有用到)。
- 会在 worker 节点上起 2 个(由 —num-executors 指定)executor,每一个 executor 最大能分配 2G(由 —executor-memory 指定)的内存,并最大支持 2 个(由—executor-cores 指定)task 的并发执行。
-
yarn-cluster 模式的资源计算
这里的 spark.driver.cores 默认是 1,也可以设置为更多。
资源使用的优化:
- yarn-client 模式
使用 yarn-client 模式,请参见如下配置:
--master yarn-client --driver-memory 6g –-num-executors 25 --executor-memory 4g --executor-cores 4
按照上述的资源计算公式,
- master 的资源量为:
- core:1
- mem:7G (5G + 375M 向上取整为 6G)
- workers 的资源量为:
- core: 25*4 = 100
- mem: 25*5G (4G + 375M 向上取整为 5G) = 125G
可以看到总的资源没有超过集群的总资源,那么遵循这个原则,您还可以有很多种配置,如计算超大数据,可将executor-memory调大,参考如下参数:
--master yarn-client --driver-memory 5g –-num-executors 8 --executor-memory 18g --executor-cores 4
- yarn-cluster 模式
当使用 yarn-cluster 模式后,Driver 程序会被放到 worker 节点上。资源会占用到 worker 的资源池里面,参数设置请参考如下配置:
--master yarn-cluster --driver-memory 5g --num-executors 15 --executor-memory 4g --executor-cores 4
- standalone模式
在standalone模式下,如现有10个worker节点,每个worker节点4核8G,那么就可以设置:
--master spark://host:port --executor-memory 8g --total-executor-cores 40
配置建议:
-
executor_cores*num_executors
表示的是能够并行执行Task的数目不宜太小或太大!一般不超过总队列 cores 的 25%,比如队列总 cores 400,最大不要超过100,最小不建议低于40,除非日志量很小。 -
executor_cores
不宜为1!否则 work 进程中线程数过少,一般 2~4 为宜。 -
executor_memory
一般 6~10g 为宜,最大不超过64G,否则会导致GC代价过高,或资源浪费严重。 -
driver-memory
关于driver memory在程序运行时到底应该给多少:
一般认为:driver不做任何计算和存储,只是下发任务与yarn资源管理器和task交互,一般4-6g即可。
但是最近在一次计算任务中,发生了java.lang.OutOfMemoryError: GC overhead limit exceeded:
参考此文章对于driver memory和executor memory的描述,executor memory设置的较大时,driver memory也应该相应增大:driver memory并不是master分配了多少内存,而是管理多少内存。换言之就是为当前应用分配了多少内存。
executor memory是每个计算节点上占用的内存。每一个节点可使用内存。也就是实际计算过程中用到的计算内存。
实际应用中,初步感觉executor memory受限于driver memory。当executor memory设置特别大,而driver memory默认时,应用可分配的内存依然很小,数据达到一定程度就会爆栈。故而当前一般先设置DM(driver memory),随后根据集群情况、任务大小等实际情况来设置EM(executor memory)。 -
增加每个executor的内存量,增加了内存量以后,对性能的提升,有三点:
- 如果需要对RDD进行cache,那么更多的内存,就可以缓存更多的数据,将更少的数据写入磁盘,
甚至不写入磁盘。减少了磁盘IO。 - 对于shuffle操作,reduce端,会需要内存来存放拉取的数据并进行聚合。如果内存不够,也会写入磁盘。如果给executor分配更多内存以后,就有更少的数据,需要写入磁盘,甚至不需要写入磁盘。减少了磁盘IO,提升了性能。
- 对于task的执行,可能会创建很多对象.如果内存比较小,可能会频繁导致JVM堆内存满了,然后频繁GC,垃圾回收 ,minor GC和full GC.(速度很慢).内存加大以后,带来更少的GC,垃圾回收,避免了速度变慢,性能提升。
- 如果需要对RDD进行cache,那么更多的内存,就可以缓存更多的数据,将更少的数据写入磁盘,
另外还可能需要添加的一些配置:
//解决连接超时
--conf spark.network.timeout = 100000000
//设置Spark对每个action结果集大小的限制
--conf spark.driver.maxResultSize = 15g
//executor-memory超量使用的范围
--conf spark.executor.memoryoverhead = 4096m