一次spark作业执行后进程无法关闭的原因及解决方案

最近运维的同学频频反映,spark集群作业模式,每次执行完成spark的进程端口都已经关闭了,但是通过命令执行spark作业的进程和端口却无法自动关闭,严重影响其他业务组的作业运行,但是无法关闭的情况不是经常出现,出现频率也不规范,但是执行任务正常,数据清洗加工正常,存储正常,查看日志发现是在作业执行完成会执行sparksession.stop方法,是这个方法堵塞了进程的正常关闭,但是原因从日志上无法分析,考虑从jvm层面进行分析查看,是否是因为内存或者cpu的原因导致,用-jstack -pid 命令进行打印jvm的堆栈:

只复制部分堆栈:

从堆栈上大致可以看出是main函数的sparksession.stop的线程堵塞了,线程的几种状态在这就不细说了,大家可以自己在google和百度自行查找,但是是什么原因的,仔细一看发现是在等待某个锁的释放,但是为什么会被锁住呢,只能在stop的方法进行查看源码分析了:

看到synchronized关键字大概能明白了,应该是锁住了,所以寻找锁住的原因,在堆栈中进行find发现了这样的一个线程信息

一看原来是这个线程获取到了锁,但是为什么进行waiting呢,这个是将要解决的问题了,仔仔细细的看了下,发现应该是跟spark的ContextCleaner有关,这个方法是用来清理内存空间的残留数据,但是它本是个守护线程,并且在作业运行过程中就已经进行清理了,难道是因为一直在清理内存,但仔细想来也不会,因为如果一直在清理空间的话,守护线程怎么会waiting呢,所以又看了一遍发现又找到一个可以看懂的内容:

at org.apache.spark.rpc.RpcTimeout.awaitResult(RpcTimeout.scala:81)

Rpc协议超时?原来是spark进行心跳检测通信的时候超时了,但是询问运维的同学,在堵塞的期间,并没有网络异常报警或者内存空间占满报警,所以应该不是这2个原因,然后google了一下,发现大佬们基本给出2个答案:

1)spark节点宕机了(当然不可能)

2)引发这个问题是由于数据发生了倾斜,导致STW,缩短GC时间可以解决

所以在spark的启动命令加入动态conf参数:

--conf "spark.driver.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC

--conf "spark.executor.extraJavaOptions=-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC

使用了CMS的回收站(jvm参数配置的简单,也可以配置新生代老年代的内存空间,以及回收站),同时修改了spark.network.timeout 从36s改为默认120s,目前运行几天并没有出现以往情况,心里有点窃喜,哈哈,但是不确定是否是因为此原因,所以有明确处理经验的朋友可以留言给我,感谢!。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值