Spark作业在Yarn上长时间运行后失败求助
看起来你在运行Spark ML Pipeline做Word2Vec+逻辑回归的超参优化时碰到了棘手的通信问题——ClosedChannelException加上Yarn调度器和AM通信失败,我来帮你拆解下问题并给出可行的解决思路:
先分析错误根源
这个错误本质上是Spark Driver/Executor和YARN Application Master(AM)之间的通信链路被意外关闭了,结合你的配置和场景,大概率是这几个原因:
- 你设置的超长时间网络超时(10000000毫秒≈2.7小时)反而触发了系统或YARN的连接回收机制,导致连接失效
- Executor资源配置超出了集群的实际承载能力,引发资源竞争,部分Executor被YARN强制杀掉
- 超参网格的组合数过多(96种),任务运行时间过长,加剧了通信链路的不稳定
具体解决步骤
1. 把离谱的网络超时参数调回合理范围
你当前的spark.network.timeout和spark.executor.heartbeatInterval设置得太大了,YARN或系统层面可能会认为长期无响应的连接已经失效,直接关闭。建议改成更稳妥的数值:
"spark.network.timeout": "300s", "spark.executor.heartbeatInterval": "60s"
这个范围既能覆盖长任务的执行时间,又不会让连接处于“假死”状态被系统回收。
2. 修正Executor资源配置,避免资源过载
你的集群是4台r4.2xlarge(每台8核61GB内存),但当前配置的spark.executor.instances=19 + spark.executor.cores=2,总核数达到了38,远超集群总可用核数(4*8=32),这会导致部分Executor无法正常启动,或者被YARN强制终止。调整成匹配集群资源的配置:
"spark.executor.memory": "13G", "spark.executor.cores": "2", "spark.executor.instances" : "16", "spark.yarn.executor.memoryOverhead" : "1536", "spark.default.parallelism" : "32"
解释下:每台节点分配4个Executor(8核/2核=4),4台就是16个;每个Executor内存13G,加上1.5G的Overhead,单节点内存占用4*(13+1.5)=58G,预留3G给系统进程,刚好适配r4.2xlarge的61GB内存。
3. 缩小超参搜索的规模,降低计算负载
你的ParamGrid组合数是22223*2=96种,这会让Pipeline重复执行96次,不仅运行时间极长,还会持续占用大量集群资源,增加通信失败的概率。可以这么优化:
- 分阶段调参:先固定LR参数,只搜索Word2Vec的
windowSize和minCount;再固定Word2Vec参数,搜索LR的maxIter和regParam - 去掉LR的
maxIter=1000——逻辑回归通常迭代100次就足够收敛,1000次纯属浪费资源 - 如果业务允许,让q1和q2的Word2Vec使用相同的参数,减少一半的计算量(不用单独给q2w2model加Grid,直接复用q1的参数)
4. 排查YARN层面的异常日志
- 查看YARN AM的日志,确认是否有Executor被OOM杀死或者资源不足的记录
- 检查集群节点的磁盘空间,避免因为磁盘满导致进程崩溃
- 查看NodeManager的日志,看看是否有网络波动或者资源调度的异常
5. 启用动态资源分配(可选)
如果你的集群还有其他任务在运行,开启动态资源分配可以让Spark根据任务需求自动调整Executor数量,避免资源浪费:
"spark.dynamicAllocation.enabled": "true", "spark.dynamicAllocation.minExecutors": "4", "spark.dynamicAllocation.maxExecutors": "16", "spark.dynamicAllocation.initialExecutors": "8"
总结
建议先从调整网络超时和Executor配置入手,这两个是最直接的诱因,然后再逐步优化超参搜索的规模。如果还是有问题,再去排查YARN的日志,看看是否有更深层的集群资源问题。
内容的提问来源于stack exchange,提问作者Mustufain

