Java 火花驱动器&x27;s RMI库导致完全GC暂停(System.GC())

Java 火花驱动器&x27;s RMI库导致完全GC暂停(System.GC()),java,apache-spark,garbage-collection,jvm,garbage,Java,Apache Spark,Garbage Collection,Jvm,Garbage,我们的Spark executors日志包含以下内容: org.apache.spark.rpc.RpcTimeoutException: Futures timed out after [10 seconds]. This timeout is controlled by spark.executor.heartbeatInterval 我发现这些是从执行者到驱动程序的心跳,我怀疑驱动程序上存在GC问题,因此启用了GC日志记录,并发现以下问题: [Full GC (System.gc())

我们的Spark executors日志包含以下内容:

org.apache.spark.rpc.RpcTimeoutException: Futures timed out after [10 seconds]. This timeout is controlled by spark.executor.heartbeatInterval
我发现这些是从执行者到驱动程序的心跳,我怀疑驱动程序上存在GC问题,因此启用了GC日志记录,并发现以下问题:

[Full GC (System.gc()) 5402.271: [CMS: 10188280K->8448710K(14849412K),27.2815605 secs] 10780958K->8448710K(15462852K), [Metaspace: 93432K->93432K(96256K)], 27.2833999 secs] [Times: user=27.28 sys=0.01, real=27.29 secs]
显然,有东西调用了System.gc(),导致驱动程序上的gc长时间暂停(27秒)。进一步看,RMI是可疑的,因为这些
System.gc()
调用恰好每30分钟发生一次。
我在Spark driver上找不到与RMI有关的此问题的任何参考。我是否应该通过设置
-XX:+DisableExplicitGC

来禁用
System.gc()
调用?

有趣的是,我刚刚研究了一个类似的问题。我可以看到Spark中的一些代码实际上调用了
System.gc()

也许值得在Spark中开一个JIRA来讨论这个问题

我知道使用
System.gc()
进行调用不是最佳做法,主要是因为它会停止所有其他对性能有重大影响的线程。但是,我可以在Java Oracle文档中看到,为了同时运行
System.gc()
(-XX:+ExplicitGCInvokesConcurrent),从Java 1.6开始引入了一个额外的JVM参数:

您可以尝试将其设置为附加参数:

spark.executor.extraJavaOptions=“-XX:+explicitgchinvokesconcurrent”

根据设置参数的方式,您可以将其放入Spark的配置文件中,也可以在Spark命令(Spark submit、Spark shell等)中使用--conf行参数传递它

更新:

在Spark 2.x的ContextCleaner.scala文件中找到以下注释:

/**
* How often to trigger a garbage collection in this JVM.
*
* This context cleaner triggers cleanups only when weak references are  garbage collected.
* In long-running applications with large driver JVMs, where there is little memory pressure
* on the driver, this may happen very occasionally or not at all. Not  cleaning at all may
* lead to executors running out of disk space after a while.
*/

在实际的垃圾收集方面,
System.gc()
实际上会做什么,以及如何做,这还没有定义。文档只说“提供了一个提示”。你是指我提供的链接吗?它只是作为-XX:+ExplicitGCInvokesConcurrent参数的参考,假设System.gc()调用得到了执行,并且JVM实际启动了gc,那么这将非常有用。如果它是一个显式GC,那么它肯定会对性能产生影响,因为它会暂停JVM中的所有线程。