火花上的火花,容器退出时使用非零退出代码143

时间:2016-12-06 18:28:54

标签: apache-spark hive yarn hortonworks-data-platform

我正在使用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

在此错误之前,我没有看到任何WARN或ERROR日志。 问题是什么?我应该在哪里寻找内存消耗? 我在SparkUI的 存储 标签中看不到任何内容。 该日志取自HDP 2.5上的纱线资源管理器UI

修改 看着容器日志,好像是java.lang.OutOfMemoryError: GC overhead limit exceeded

我知道如何增加内存,但我已经没有任何记忆了。 如何在没有出现此错误的情况下使用4个Dataframe进行笛卡尔/产品连接。

3 个答案:

答案 0 :(得分:4)

我也遇到了这个问题并尝试通过引用一些博客来解决它。 1.运行spark add 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时,您将收到以下消息:
  2. 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. 当有更多内存资源可用时,尝试为执行程序或驱动程序添加更多内存:

    3.   

      - executor-memory 10000m \
        --driver-memory 10000m \

      1. 对于我的情况:PSYoungGen的内存小于ParOldGen,导致许多年轻对象进入ParOldGen内存区域并最终 ParOldGen不可用。所以java.lang.OutOfMemoryError:出现Java堆空间错误。

      2. 为执行者添加conf:

      3.   

        ' spark.executor.extraJavaOptions = -XX:NewRatio = 1 -XX:+ UseCompressedOops   -verbose:gc -XX:+ PrintGCDetails -XX:+ PrintGCTimeStamps'

        -XX:NewRatio =率 rate = ParOldGen / PSYoungGen

        它依赖。您可以尝试GC战略,如

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

        Java Concurrent and Parallel GC

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

答案 1 :(得分:3)

所有容器的日志文件和我可以使用

yarn logs -applicationId application_1480922439133_0845_02

如果您只想要AM日志,

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已经快速连续运行,但无法恢复太多内存。唯一的原因是,编写的代码编写得很差并且有很多反向引用(这很可疑,因为你正在进行简单的连接),或者已经达到了内存容量。

答案 2 :(得分:0)

原因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)
 })