Spark Worker进程OOM后JVM挂起相关问题咨询
Spark Worker节点OOM与SIGTERM信号相关问题解答
问题背景
Spark Worker节点出现如下OOM异常:
Exception in thread "dispatcher-event-loop-14" java.lang.OutOfMemoryError: GC overhead limit exceeded at java.util.HashMap.newNode(HashMap.java:1747) at java.util.HashMap.putVal(HashMap.java:631) at java.util.HashMap.put(HashMap.java:612) at java.util.HashSet.add(HashSet.java:220) at java.io.ObjectStreamClass.getClassDataLayout0(ObjectStreamClass.java:1317) at java.io.ObjectStreamClass.getClassDataLayout(ObjectStreamClass.java:1295) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1480) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548) at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509) at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432) at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178) at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348) at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:43) at org.apache.spark.rpc.netty.RequestMessage.serialize(NettyRpcEnv.scala:557) at org.apache.spark.rpc.netty.NettyRpcEnv.send(NettyRpcEnv.scala:192) at org.apache.spark.rpc.netty.NettyRpcEndpointRef.send(NettyRpcEnv.scala:520) at org.apache.spark.deploy.worker.Worker.org$apache$spark$deploy$worker$Worker$$sendToMaster(Worker.scala:638) at org.apache.spark.deploy.worker.Worker$$anonfun$receive$1.applyOrElse(Worker.scala:524) at org.apache.spark.rpc.netty.Inbox$$anonfun$process$1.apply$mcV$sp(Inbox.scala:117) at org.apache.spark.rpc.netty.Inbox.safelyCall(Inbox.scala:205) at org.apache.spark.rpc.netty.Inbox.process(Inbox.scala:101) at org.apache.spark.rpc.netty.Dispatcher$MessageLoop.run(Dispatcher.scala:216) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Java HotSpot(TM) 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGTERM to handler- the VM may need to be forcibly terminated.
异常发生前,Worker因Executor反复退出(退出码Code 1、exitStatus 1)而不断重启Executor。相关配置如下:
- Worker进程
-Xmx=1GB - 节点总内存=100GB
- Java 8
- Spark 2.2.1
异常发生时系统内存90%处于空闲状态,但Worker进程仍存活,却已与Master断开关联且停止处理任务。推测是反复提交Executor导致Worker进程OOM,此时有进程向Worker JVM发送了SIGTERM信号,JVM处理该信号时再次触发OOM。
问题解答
1. 哪个进程可能发送了SIGTERM信号?
最可能的发送方有两个:
- Spark Master进程:当Worker因OOM导致心跳中断、无法响应Master的状态请求时,Master会判定Worker失联,主动发送SIGTERM信号尝试清理无效进程。
- 系统OOM Killer:如果Worker所在的资源隔离组(如cgroup)内存配额耗尽,或系统出现临时内存波动,OOM Killer可能误判并发送信号。但结合节点90%内存空闲的情况,Spark Master发送信号的概率更高。
2. 系统内存充足的情况下,为何该进程会发送该信号?OOM时JVM难道不会自行退出吗?
- 系统总内存充足,但Worker自身堆内存仅配置1GB,反复重启Executor会导致Worker内部积累大量状态数据(如启动请求、失败记录、RPC消息队列),触发GC overhead limit exceeded——这种OOM属于JVM软限制,默认不会直接终止进程,仅抛出异常,此时Worker已无法正常处理任务和心跳。
- Master长时间收不到Worker心跳,会认定Worker故障,因此发送SIGTERM信号尝试终止进程、重新分配资源。
3. JVM处理SIGTERM信号时为何会出现OOM?
JVM收到SIGTERM后会触发优雅关闭流程:停止新任务、清理资源、关闭线程池,甚至可能需要序列化状态向Master发送最后报告。此时Worker堆内存已极度紧张,GC无法释放足够空间,而优雅关闭中的序列化操作(如栈日志中的ObjectOutputStream.writeObject)需要分配新内存,因此再次触发OOM。
4. 为何Worker进程仍处于运行状态?
GC overhead limit exceeded属于非致命OOM,JVM不会立刻终止进程,仅持续抛出异常,允许线程尝试继续执行。- 处理SIGTERM的线程触发OOM后,优雅关闭流程被中断,JVM的终止逻辑未执行完成,导致Worker卡在“半死不活”状态:无法处理任务和心跳,但进程本身未完全退出。
内容的提问来源于stack exchange,提问作者Calypso
相关产品推荐
相关产品推荐

