java Spark工作进程中的OutOfMemoryError使JVM处于挂起状态

ct2axkht  于 2023-03-06  发布在  Java
关注(0)|答案(2)|浏览(119)

我在spark worker节点中遇到此异常

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.

就在此异常工作进程在执行器退出时重复启动执行器之前:-

EXITING with Code 1 and exitStatus 1

配置:-

    • 用于工作进程的Xmx = 1GB
  • 工作节点上的总RAM = 100 GB
  • java 8
  • Spark2.2.1

发生此异常时,90%的系统内存是可用的。在此异常之后,进程仍在运行,但此工作进程已与主进程解除关联,并且不处理任何内容。
现在,对于https://stackoverflow.com/a/48743757线程,我所理解的是,由于重复提交执行器,工作进程面临OutOfMemory问题。此时,一些进程将SIGTERM发送到工作JVM,并且在处理此JVM时面临OutOfMemory问题。
1.哪个进程可以发送SIGTERM?
1.既然有足够的系统内存可用,为什么操作系统或任何进程发送信号,在内存不足的情况下,JVM不应该自己退出吗?
1.当jvm处理SIGTERM时,为什么会发生内存不足?
1.为什么程序还在进行?

t40tm48m

t40tm48m1#

观察员确认那不是Kubernetes而是VM

  • 工作节点上的总RAM = 100 GB *
  • 工作节点 * 是虚拟机。

您是否尝试过增加may堆大小-Xmx3000m

ej83mcc0

ej83mcc02#

1.哪个进程可能发送了SIGTERM?

理论上,用户范围内的任何进程都可以发送信号。即运行JVM的同一个用户或root用户。它可以是用于监视JVM响应的守护进程(类似于Apache Commons Daemon)。如何跟踪信号来自何处可能在ServerFault或SuperUser上询问更好。

2.既然有足够的系统内存可用,为什么操作系统或任何进程发送信号,在OutOFMemory问题的情况下,JVM不应该自行退出吗?

我们不知道为什么会发送SIGTERM。但是这个信号是一个关闭请求,JVM会通过运行shutdown钩子来响应,并自行退出。如果它已经进入OutOfMemory,这就很困难了。接下来你通常会发送SIGKILL,它告诉操作系统删除这个进程。
您可以通过执行https://serverfault.com/a/826779来自动触发SIGKILL

3.当jvm处理SIGTERM时,为什么会发生内存不足?

确切的原因可以在你运行的应用程序中找到,结合它需要处理的事件和数据。对于服务器应用程序来说,当它们关闭时运行关闭代码是很常见的。
通常JVM在遇到OutOfMemoryError后会处于无效状态。原因是一些对象无法再被分配,并且在抛出错误(并在各种catch close中处理它,将其记录到磁盘等)时,它再次需要分配内存,这也很容易失败。

**4.为什么进程仍在运行?**JVM未成功处理关闭请求,因为它处于非正常状态。因此进程未自行终止,操作系统没有理由强制终止。
后续步骤

对于操作来说,增加JVM内存总量并执行正常重启可能是合适的。棘手的是,需要内存的代码通常不是没有及时释放内存的罪魁祸首,因此错误的堆栈跟踪可能会产生误导。您必须分析内存使用情况,这在Using HeapDumpOnOutOfMemoryError parameter for heap dump for JBoss中有效。还可以考虑激活https://serverfault.com/questions/826735/how-to-restart-java-app-managed-by-systemd-on-outofmemory-errors
对于开发人员来说,减少JVM总内存以轻松重现这种情况并分析操作的日志和堆转储可能是有意义的。

相关问题