version:2.4.0-cdh6.3.0
配置属性的2种方式:
对于未设置的属性,spark会使用默认值。
spark属性大致可以分为两类:
文档中提及的属性清单
https://spark.apache.org/docs/latest/configuration.html
大多数默认值是合理、有效、可以通用的,但以下几项需要依据集群配置、提交作业的大小进行额外的设置
spark 和内存、cpu相关的属性及其默认值
属性 | 默认值 | 说明 |
---|---|---|
spark.driver.memory | 1G | |
spark.driver.memoryOverhead | driverMemory * 0.10, with minimum of 384 | |
spark.executor.memory | 1G | |
spark.executor.memoryOverhead | executorMemory * 0.10, with minimum of 384| | |
spark.driver.cores | 1 | |
spark.executor.cores | yarn模式下默认是1 |
属性 | 值 | 说明 |
---|---|---|
spark.executor.instances | 60 | 定义作业所需的容器(executor)数量N,能有多少取决于集群内可以分配给容器的总的内存M和总的cpu核数C, spark.executor.memory= x 1 x_1 x1, spark.executor.cores= x 2 x_2 x2, N = m i n ( M / x 1 , C / x 2 ) N=min(M/x_1,C/x_2) N=min(M/x1,C/x2) 主要取决于你准备给一个容器分配几G内存,然后准备给容器分配多少个CPU内核,或者反着来推算 |
spark.executor.memory | 3G | 为容器分配的内存大小 |
spark.executor.cores | 2 | 为容器分配的cpu核数,如果集群cpu有空闲可以增加 |
spark.executor.memoryOverhead | 1G | 设置容器内堆外内存的大小 |
常看到文章中说分配给容器的cpu核数会影响容器内task的数量
在spark的代码中可以看到如下的配置属性,默认值为1
private[spark] val CPUS_PER_TASK = ConfigBuilder("spark.task.cpus").intConf.createWithDefault(1)
引用自https://spark.apache.org/docs/2.4.0/cluster-overview.html
之所以关注内存的问题,主要是为了应对应用中可能出现的OOM问题
spark中的OOM大致有两类driver端OOM和executor端OOM
例如:
ExecutorLostFailure (executor 710 exited caused by one of the running tasks) Reason:
Container killed by YARN for exceeding memory limits. 1.5 GB of 1.5 GB physical memory used. Consider boosting
spark.yarn.executor.memoryOverhead or disabling yarn.nodemanager.vmem-check-enabled because of YARN-4714.
yarn.nodemanager.resource.memory-mb //每个NodeManager可以供yarn调度(分配给container)的物理内存,单位MB
yarn.nodemanager.resource.cpu-vcores //每个NodeManager可以供yarn调度(分配给container)的vcore个数
yarn.scheduler.maximum-allocation-mb //每个container能够申请到的最大内存
yarn.scheduler.minimum-allocation-mb //每个container能够申请到的最小内存,如果设置的值比该值小,默认就是该值
yarn.scheduler.increment-allocation-mb //container内存不够用时一次性加多少内存 单位MB。CDH默认512M
yarn.scheduler.minimum-allocation-vcores //每个container能够申请到的最小vcore个数,如果设置的值比该值小,默认就是该值
yarn.scheduler.maximum-allocation-vcores //每个container能够申请到的最大vcore个数。
yarn.nodemanager.pmem-check-enabled //是否对contanier实施物理内存限制,会通过一个线程去监控container内存使用情况,超过了container的内存限制以后,就会被kill掉。
yarn.nodemanager.vmem-check-enabled //是否对container实施虚拟内存限制
引用自:https://blog.csdn.net/wisgood/article/details/51436060
spark 1.5版本之前的内存管理模式,将heap space严格划分成固定大小的区域,如果没有对应用进行调优,估计会经常出现内存溢出问题。
在spark 2.4.0时默认关闭,通过设置spark.memory.useLegacyMode=true可以启用,默认是false。
虽然是早期的内存管理模式,但是可以借助它理解spark的内存管理、内存分配模式。
引用自https://www.cnblogs.com/yangsy0915/p/5118100.html
引用自:https://www.cnblogs.com/zz-ksw/p/11403622.html
容器内存由:spark.executor.memory、spark.executor.memoryOverhead两大部分组成
spark.executor.memory中又划分出spark.shuffle.memoryFraction和
在官方文档中可以看到2.4.0版本中这个属性已弃用,当spark.memory.useLegacyMode=true时这个配置属性会读取这个属性
数据在shuffle时,如果内存中的数据大小超出这个限制,内存中的数据会溢出到磁盘中。如果经常发生溢出(spill),可以考虑增加spark.storage.memoryFraction来减少数据溢出。
说明:每个executor分配的堆外内存数量,除非另有说明,否则这一部分作为内存使用,主要当作虚拟内存、内部字符存储、其它本机开销。这部分内存的大小随着spark.executor.memory的增大而增大,通常是6%-10%,这个属相在yarn、kubernets模式下支持
计算公式:max(executorMemory*0.10,384)
取值范围:[384, + ∞ +\infty +∞ )
单位:MB
容器内的task共享spark.executor.memory,task运行时使用这一部分的内存,也就是说当spark.executor.memory不足时,会占用spark.executor.memoryOverhead ,当加上spark.executor.memoryOverhead也不够时,会一次性增加yarn.scheduler.increment-allocation-mb大小的内存默认是512M
到这里,总算明白为什么报错信息会让你调整spark.yarn.executor.memoryOverhead的大小,但是这不是根本原因,根本原因是spark.executor.memory设置的太小了!!!!。
在yarn模式下,容器内存不足时会一次性增加yarn.scheduler.increment-allocation-mb大小的内存默认是512M,如果还是不够,就会被yarn kill掉,也就出现了下面的报错
ExecutorLostFailure (executor 710 exited caused by one of the running tasks) Reason:
Container killed by YARN for exceeding memory limits. 1.5 GB of 1.5 GB physical memory used. Consider boosting
spark.yarn.executor.memoryOverhead or disabling yarn.nodemanager.vmem-check-enabled because of YARN-4714.
这个需要尝试不同的组合,个人认为内存一定要管够,否则任务挂掉了就直接没了,cpu给的少也只是跑的慢一些。
task是spark的最小作业单元
毫无疑问,task跑的越安全、越快,失败次数越少,应用执行的就越快越稳,其它都是次要的!!!
回到上面的异常中去,解决措施如下:
一倍一倍的进行调整
增大spark.executor.memory
或
减少spark.executor.cores
目的是让容器中的每个task得到比之前更多的内存
默认配置下spark.executor.memory和spark.executor.cores的比例是1:1
可以试试2:1、3:1、4:1等等
参考资料:
Spark官方文档
Spark中的内存开销问题
https://blog.csdn.net/zc19921215/article/details/103464648
Spark on Yarn 架构解析
CDH Yarn 调度资源指南 - CDH6.0.x 详解
Spark 内存架构
driver端有一个,在driver端上运行Application的main()函数,并创建SparkContext,spark通过SparkContext与ClusterManager通信,进行资源的申请,任务的分配、监控等。
executor端有多个,负责具体任务的执行
当所有executor端任务执行完毕,driver端负责将SparkContext关闭
格式
./bin/spark-submit \
--class \
--master \
--deploy-mode \
--conf = \
... # other options
\
[application-arguments]
--class 应用程序的入口
--master 集群的主URL
--deploy-mode 部署方式
--conf 配置属性
application-jar 应用程序的依赖jar包路径
application-arguments 传递给主类的 main 方法的参数
# Run on a Mesos cluster in cluster deploy mode with supervise
./bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master mesos://207.184.161.138:7077 \
--deploy-mode cluster \
--supervise \
--executor-memory 20G \
--total-executor-cores 100 \
http://path/to/examples.jar \
1000
最后的100是传递给org.apache.spark.examples.SparkPi的参数(传递给main函数的参数)
参考资料:
spark-submit简要说明