应用程序内存和CPU分配
local模式 — 不需要安装 spark,也不需要启动 spark 集群
standalone模式 — 需要安装 spark,需要启动 spark 集群。
yarn模式 — 需要安装 spark,但不需要启动 spark 进群。
在 spark-default.conf 文件中设置 spar k的资源配置,资源分配参数为 spark.xxx;如 spark.driver.cores。
有三种方式设置 spark 的配置属性,其优先级从高到低。
- 在程序代码中通过 sparkConf 对象设置;
- 通过 spark-submit 任务提交工具设置;
- 通过 spark-default.conf 文件配置。
优先级:Spark-default.conf < spark-submit –conf < SparkConf代码
spark-submit --master spark://bigdata01:7077
--conf spark.executor.memory=1201m
--conf spark.executor.cores=1
--class sparkcore.learnTextFile /opt/sparkapp/learnTextFileCode.jar
如
spark .executor.memory 8G
spark.driver.memory 16G
spark.driver.maxResultSize 8G
spark.akka.frameSize 512
如在 spark-env.sh 中:
从 webUI 上可以看出,每个 worker 节点都启动了两个 executor,一个 core 核心和 900m 内存。
应用程序的资源分配实战
如果在配置中设置 单个 executor 的 cores 数量超过了可申请 cores 的数量,程序没法启动运行。
例如:
spark-submit --master spark://bigdata01:7077
--executor-memory 900m
--executor-cores 6
--class sparkcore.learnTextFile /opt/sparkapp/learnTextFile.jar
如果 worker 有足够的资源,对于同一个应用,会在每个 worker 节点上启动多个 executor。
spark-submit --master spark://bigdata01:7077
--executor-memory 918m
--executor-cores 1
--class sparkcore.learnTextFile /opt/sparkapp/learnTextFile.jar
另一种参数赋值的方式 --conf PROP=VALUE
spark-submit --master spark://bigdata01:7077
--conf spark.executor.memory=1201m
--conf spark.executor.cores=1
--class sparkcore.learnTextFile /opt/sparkapp/learnTextFile.jar
常见配置项
Spark 常用配置项,主要是对 Spark 运行过程中各个使用资源的地方,通过调整参数值,优化资源使用效率,提升 Spark 作业性能。
num-executors
该参数用于设置 Spark 作业需要使用多少个 Executor 进程来执行。Driver 向 Yarn 集群管理器申请资源时,Yarn 集群管理器会尽可能按照设置参数来在集群的各个 worker 节点上,启动相应数量的 Executor 进程。默认参数只会提供少量的 Executor 进程,此时 Spark 作业的运行速度是非常慢的。
该参数设置的太少,将无法充分利用集群资源;如果参数设置太多,大部分队列可能无法给与充分的资源。
executor-memory(spark.executor.memory)
该参数用于设置每个 Executor 进程的内存。Executor 内存的大小,很多时候直接决定了 Spark 作业的性能,而且跟常见的额 JVM OOM 异常,也有直接关系。
每个 Executor 进程的内存设置 4G ~ 8G 较为合适。但是这只是一个参考值,具体的设置还需要根据不同部门的资源队列来决定。如果有其他部门方向该内存资源,那么建议申请的内存大小最好不要超过总内存资源的 1/3 ~ 1/2,避免自己的 Spark 作业占用所有资源而导致其他作业无法运行。
executor-cores(spark.executor.cores)
该参数用于设置每个 Executor 进程的 CPU core 数量。这个参数决定了每个 Executor 进程并行执行 task 线程的能力。因为每个 CPU core 同一时间只能执行一个task线程,因此每个 Executor 进程的 CPU core 数量越多,越能快速地执行完分配给自己的所有 task 线程。
Executor 的CPU core 数量设置为 2~3 个比较合适,但是也必须根据不同部门的资源队列来决定。
如果与其他部门共享这个资源,那么建议申请的CPU core不能超过总CPU cores的 1/3 ~ 1/2左右,这样可以避免影响其他作业的运行。
driver-memory
该参数用于设置 driver 进程的内存。
Driver 的内存通常不需要设置,或者设置 1G 左右。但是如果需要设置 collect 算子将 RDD 的数据全部拉去到 Driver上进行处理,那么必须确保 Driver 的内存足够大,否则将出现 OOM 内存溢出的问题。
spark.defaultparallelism
该参数用于设置每个 stage 的默认 task 数量。
建议:spark 作业的默认 task 的数量为 500 ~ 1000 个较为合适。如果不设置这个参数,那么此时就会导致 spark 自己根据底层 HDFS 的 block 数量来设置 task 数量,默认是一个HDFS block 对应一个 task。通常来说,spark 默认设置的数量偏少的。如果 taks 数量偏少,就会导致 executor 没法提升性能。
例如:如果 task 只有一个或者几个,那么 90% 的 executor 进程可能根本没有 task 执行,只能浪费资源。
因此,建议该值设置为:num-executors * executor-cores 的 2~3 倍较为合适。
spark.storage.memoryFraction
该参数用于设置 RDD 持久化数据在 executor 内存中所占的比例,默认是 0.6。即 executor 中 60% 的内存用来保存持久化的 RDD 数据。
在 spark 作业中,如果有较多的 RDD 持久化操作,那么该值可以考虑提高些。也就是说提高 RDD 持久化所占内存的比例,保证持久化数据能够被容纳在内存中,避免内存不足的情况下缓存更多的数据到磁盘,降低性能能。
但是如果 spark 作业要进行比较多的 shuffle 操作,而持久化的操作比较少,那么这个参数值可以降低点,让 shuffle 操作所占用的内存提高,而 RDD 持久化的内存减少。
当在作业中频繁的出现 GC 操作,那么表示进行算子操作的内存是比较不够用的,那么需要降低该值。
spark.shuffle.memoryFraction
该参数用于设置 shuffle 操作中能过使用的 executor 内存的比例,默认是0.2。也就是说:executor 会默认分配 20% 的内存用于进行 shuffle 算子的操作。shuffle 操作在进行聚合时,如果发现使用的内存超过了 20% 的限制,那么多余的数据将会溢写到磁盘文件中。此时将会降低性能。
如果 spark 作业中的 RDD 持久化操作比较少,且 shuffle 操作比较多时,建议降低持久化操作 spark.storage.memoryFraction 的内存所占的比例,提高 shuffle 操作的内存所占的比例,避免 shuffle 过程中数据过多时内存不够用,溢写到磁盘,降低性能。
如果频繁的 GC 导致运行缓慢,意味着 task 执行用户代码的内存不够用,那么这个参数值依旧需要降低。
注:如果发生频繁的 GC,是因为 JVM 不够用了,因为 executor 就是运行在 JVM 中,那么就需要保证 JVM 的内存不被完全使用,因此需要降低 spark.storage.memoryFraction 或者 spark.shuffle.memoryFraction 的比例值。
而且还要知道 executor-memory 是系统分配个 executor 的内存大小,其值由 spark.storage.memoryFraction 和 spark.shuffle.memoryFraction,以及其它保留等所共同决定的。
在 standalone 模式下,因为 executor 是进程级别,对应一个 JVM 的进程。task 是线程级别。而 worker 表示实体的节点设备。一个 worker 节点可以有多个 executor 进程,一个 executor 进程可以有多个 task 线程。同时一个 task 线程对应一个 CPU core。
资源参数的调优,没有固定的参数值。需要根据项目的实际情况进行设置。