在纱线上发生火花,带有非零退出代码143的容器



我正在使用HDP 2.5,运行 spark-Submit 作为纱线群集模式。

我试图使用数据帧交叉加入生成数据。即

val generatedData = df1.join(df2).join(df3).join(df4)
generatedData.saveAsTable(...)....

df1 存储级别是memory_and_disk

df2,df3,df4 存储级别是memory_only

DF1具有更多的记录,即500万,而DF2至DF4最多有100个记录。这样做我的解释是,使用 broadcastNestedloopjoin 解释计划。

由于某种原因,它总是失败。我不知道如何调试它以及内存爆炸的位置。

错误日志输出:

16/12/06 19:44:08 WARN YarnAllocator: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
16/12/06 19:44:08 WARN YarnSchedulerBackend$YarnSchedulerEndpoint: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
16/12/06 19:44:08 ERROR YarnClusterScheduler: Lost executor 1 on hdp4: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal
16/12/06 19:44:08 WARN TaskSetManager: Lost task 1.0 in stage 12.0 (TID 19, hdp4): ExecutorLostFailure (executor 1 exited caused by one of the running tasks) Reason: Container marked as failed: container_e33_1480922439133_0845_02_000002 on host: hdp4. Exit status: 143. Diagnostics: Container killed on request. Exit code is 143
Container exited with a non-zero exit code 143
Killed by external signal

在此错误之前,我没有看到任何警告或错误日志。问题是什么?我应该在哪里寻找内存消耗?我看不到SparkUI的存储 TAB。该日志从HDP 2.5

上取自 YARN Resource Manager UI

编辑查看容器日志,似乎是java.lang.OutOfMemoryError: GC overhead limit exceeded

我知道如何增加内存,但是我没有任何记忆。我该如何进行笛卡尔/产品与4个数据范围加入,而不会遇到此错误。

我也遇到了这个问题,并尝试通过引用某些博客来解决它。1.运行火花添加Conf Bellow:

--conf 'spark.driver.extraJavaOptions=-XX:+UseCompressedOops -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps' 
--conf 'spark.executor.extraJavaOptions=-XX:+UseCompressedOops -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC  ' 
  1. 当JVM GC时,您将获得关注消息:
Heap after GC invocations=157 (full 98):
 PSYoungGen      total 940544K, used 853456K [0x0000000781800000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 860160K, 99% used [0x0000000781800000,0x00000007b5974118,0x00000007b6000000)
  from space 80384K, 0% used [0x00000007b6000000,0x00000007b6000000,0x00000007bae80000)
  to   space 77824K, 0% used [0x00000007bb400000,0x00000007bb400000,0x00000007c0000000)
 ParOldGen       total 2048000K, used 2047964K [0x0000000704800000, 0x0000000781800000, 0x0000000781800000)
  object space 2048000K, 99% used [0x0000000704800000,0x00000007817f7148,0x0000000781800000)
 Metaspace       used 43044K, capacity 43310K, committed 44288K, reserved 1087488K
  class space    used 6618K, capacity 6701K, committed 6912K, reserved 1048576K  
}
  1. Psyounggen和Paroldgen均为99%,然后您将获得Java.lang.outofmemoryerror:GC高架限制超过如果创建了更多对象。

  2. 当更多内存资源可用时,请尝试为执行人或驱动程序添加更多内存:

- 遗嘱执行人记忆10000m
- 驾驶员 - 记忆10000m

  1. 对于我的情况:Psyounggen的内存比Paroldgen小,导致许多年轻物体进入Paroldgen Memory区域和Finalyparoldgen不可避免。

  2. 为执行人添加conf:

'spark.executor.extrajavaoptions = -xx:newratio = 1 -xx: usecompressedoops -verbose:gc -xx: printgcdetails -xx: printgctimestamps'

-xx:newratio =速率费率= paroldgen/psyounggen

它依赖性。您可以尝试使用GC策略,例如

-XX:+UseSerialGC :Serial Collector 
-XX:+UseParallelGC :Parallel Collector
-XX:+UseParallelOldGC :Parallel Old collector 
-XX:+UseConcMarkSweepGC :Concurrent Mark Sweep 

Java并行和平行GC

  1. 如果步骤4和步骤6都完成但仍然会出现错误,则应考虑更改代码。例如,减少ML模型中的迭代时间。

所有容器和AM的日志文件可在

上使用
yarn logs -applicationId application_1480922439133_0845_02

如果您只想要AM logs,

yarn logs -am -applicationId application_1480922439133_0845_02

如果您想找到该工作的容器,

yarn logs -applicationId application_1480922439133_0845_02|grep container_e33_1480922439133_0845_02

如果您只需要一个容器日志,

yarn logs -containerId container_e33_1480922439133_0845_02_000002

为了使这些命令工作,必须将日志聚合设置为true,否则您必须从各个服务器目录中获取日志。

更新除了尝试交换外,您无能为力,但这会降低性能。

GC高架限制的意思是,GC一直在快速连续运行,但无法恢复很多内存。唯一的原因是,要么代码写得不好,而且有很多背参考(这是令人怀疑的,因为您正在执行简单的加入),或者已经达到了内存能力。

原因1


默认情况下,洗牌计数为 200。过多的洗牌会增加使程序崩溃的复杂性和机会。尝试控制Spark会话中的造成数量。我使用以下代码将计数更改为5

implicit val sparkSession = org.apache.spark.sql.SparkSession.builder().enableHiveSupport().getOrCreate()    
sparkSession.sql("set spark.sql.shuffle.partitions=5")

另外,如果您使用的是数据框架,并且如果您不重新分配数据框,则执行将在单个执行程序中完成。如果只有1个执行人正在运行一段时间,则纱线将使其他执行者关闭。稍后,如果需要更多内存,尽管Yarn试图重新打电话给其他执行者有时不会出现,但由于内存溢出问题,该过程可能会失败。为了克服这种情况,请尝试在调用操作之前重新分配数据框。

val df = df_temp.repartition(5)

请注意,您可能需要根据您的要求更改洗牌和分区计数。在我的情况下,上述组合有效。

原因2


可能由于内存而发生的可能发生。例如,如果您使用Scala运行Spark命令,并且您正在执行大量SQL语句并导出到CSV。某些蜂巢表中的数据将非常庞大,您必须管理代码中的内存。

示例,考虑以下代码,其中lst_Sqls是包含一组SQL命令

的列表
lst_Sqls.foreach(sqlCmd => spark.sql(sqlCmd).coalesce(1).write.format("com.databricks.spark.csv").option("delimiter","|").save("s3 path..."))

运行此命令时,有时您最终会看到相同的错误。这是因为尽管Spark清除了内存,但它以懒惰的方式进行操作,即,您的循环将继续进行,但Spark可能会在以后清除内存。

在这种情况下,您需要管理代码中的内存,即执行每个命令后清除内存。为此,让我们很少更改代码。我已经评论了以下代码中的每一行所做的事情。

 lst_Sqls.foreach(sqlCmd => 
 {          
      val df = spark.sql(sqlCmd) 
      // Store the result in in-memory. If in-memory is full, then it stored to HDD
      df.persist(StorageLevel.MEMORY_AND_DISK)
      // Export to csv from Dataframe
      df.coalesce(1).write.format("com.databricks.spark.csv").save("s3 path")
      // Clear the memory. Only after clearing memory, it will jump to next loop
      df.unpersist(blocking = true)
 })

相关内容

  • 没有找到相关文章

最新更新