Spark,在EMR中抛出SparkException时的错误行为

时间:2017-09-26 06:49:19

标签: apache-spark amazon-dynamodb yarn amazon-emr

我在EMR中运行一个火花作业,YARN作为资源管理器并在2个节点上运行。如果我的条件不满足,我需要故意使步骤失败,因此下一步不会按照配置执行。 为了实现这一点,我在dynamoDB中插入日志消息后抛出了一个自定义异常。

它运行正常,但Dynamo中的记录被插入两次。

以下是我的代码。

if(<condition>) {
  <method call to insert in dynamo> 
  throw new SparkException(<msg>);
  return;
}

如果我删除该行以抛出异常,它可以正常工作但步骤已完成。

如何在不收到日志消息两次的情况下使步骤失败。

感谢您的帮助。

此致 Sorabh

1 个答案:

答案 0 :(得分:2)

您的发电机消息被插入两次的原因可能是因为您的错误条件被两个不同的执行程序命中并处理。 Spark正在划分其工作人员之间的工作,这些工人不会分享任何知识。

我不确定是什么驱使您的要求让Spark步骤失败,但我建议您在应用程序代码中跟踪该失败案例,而不是直接尝试让Spark死掉。换句话说,编写检测错误的代码并将其传递回您的spark驱动程序,然后根据需要对其进行操作。

执行此操作的一种方法是使用累加器来计算处理数据时发生的任何错误。看起来大概就是这样(我假设scala和DataFrames,但你可以根据需要适应RDD&#39;和/或python):

val accum = sc.longAccumulator("Error Counter")
def doProcessing(a: String, b: String): String = {
   if(condition) {
     accum.add(1)
     null
   }
   else {
     doComputation(a, b)
   }
}
val doProcessingUdf = udf(doProcessing _)

df = df.withColumn("result", doProcessing($"a", $"b"))

df.write.format(..).save(..)  // Accumulator value not computed until an action occurs!

if(accum.value > 0) {
    // An error detected during computation! Do whatever needs to be done.
    <insert dynamo message here>
}

这种方法的一个好处是,如果您在Spark UI中寻找反馈,您将能够在运行时看到累加器值。作为参考,这里是累加器的文档: http://spark.apache.org/docs/latest/rdd-programming-guide.html#accumulators