Spark动态分配下EMR集群Executor闲置超时被销毁问题咨询
集群配置
主节点: 1台,128GB内存,10核 核心节点: 自动扩容至10台,每台128GB内存,10核
问题描述
在EMR集群上运行启用Spark动态分配(spark.dynamicAllocation.enabled=true)的PySpark作业时,初始创建了近100个Executor,但其中近95个因3分钟闲置超时被Master销毁。实际仅需5个Executor即可运行作业,且未出现OOM问题,所有闲置Executor均因超时被销毁。
疑问:动态分配模式下Spark应仅创建所需数量的Executor,为何会额外创建大量冗余Executor?
(附历史服务器截图:显示大量Executor因闲置超时被销毁)
可能原因分析
1. 初始Executor数量与资源拆分配置不合理
- 若
spark.dynamicAllocation.initialExecutors被手动设置为较高值(比如接近100),Spark启动时会直接创建对应数量的Executor,后续再根据负载销毁闲置实例。默认情况下该值等于spark.dynamicAllocation.minExecutors,若手动调大则会触发过量创建。 - 若
spark.executor.cores设置为1核,结合集群总核数(主节点10核+10台核心节点各10核=110核),最多可创建110个Executor,与你观察到的近100个数量吻合。如果作业实际仅需5个Executor(如每个Executor分配20核),就会导致大量Executor因无任务可处理而闲置。
2. 任务初始爆发触发快速扩容
Spark动态分配基于待处理任务队列判断Executor需求。若作业初始阶段存在大量并发任务(比如宽依赖shuffle后生成的大量子任务),Spark会快速扩容至能处理所有待处理任务的Executor数量。一旦这些任务快速完成,后续无新任务队列支撑,多余Executor就会因闲置超时被销毁。
3. YARN资源调度的碎片化影响
EMR依赖YARN管理资源,若yarn.nodemanager.resource.memory-mb和yarn.nodemanager.resource.cpu-vcores配置导致节点资源被过度拆分(比如每个Executor分配内存过小),YARN会允许创建更多Executor,即使作业实际不需要这么多。
4. 动态分配扩容阈值设置过松
检查spark.dynamicAllocation.schedulerBacklogTimeout和spark.dynamicAllocation.sustainedSchedulerBacklogTimeout:
- 前者是待处理任务队列存在时,触发扩容的等待时长;
- 后者是持续有任务队列时,继续扩容的间隔时长。
若这两个值设置过小(比如默认1秒),Spark会在短时间内快速扩容到最大可能数量,后续任务完成后又快速销毁冗余Executor。
解决方案建议
- 优化Executor资源配置:根据作业实际需求设置
spark.executor.cores(比如设为10,单节点仅运行1个Executor)和spark.executor.memory,减少单节点的Executor数量,从根源避免过量创建。 - 调整动态分配初始参数:将
spark.dynamicAllocation.initialExecutors设为与spark.dynamicAllocation.minExecutors一致(比如5),避免启动阶段创建冗余Executor。 - 调大扩容阈值时长:适当增大
spark.dynamicAllocation.schedulerBacklogTimeout(比如从1秒调整为5秒),给Spark足够时间判断实际负载,避免快速过度扩容。 - 匹配YARN与Spark资源配置:确保YARN节点资源分配与Spark的Executor配置匹配,避免资源碎片化导致的过多Executor创建。
内容的提问来源于stack exchange,提问作者Vrishank

