我正在尝试分析我的火花作业中出现OutOfMemory
错误失败的问题。
我试图通过查看Spark ApplicationMaster的UI来分析问题。用户界面显示了作业的舞台和任务细分,我将我的分析重点放在遇到任务失败的舞台上。
Stage UI有一个DAG,显示在该阶段执行的实际命令/方法。
问题在于,我有150行代码进行DataFrame转换,最后只有一行执行操作 - 保存到镶木地板。 这意味着所有“蓝色框”都具有最后一行的行号。
是的,他们有一些关于方法的信息(窗口,顺序等),但我在整个代码中都有这些方法,所以我无法知道它所指的是哪一行。
如何找到代码的哪个部分遇到麻烦?
答案 0 :(得分:3)
由于您不知道哪个转换导致了问题,我建议在转换之间注入操作,以查看哪个操作将重新创建问题。
这是一个小实用功能,我用它来简化:
(我称之为<enabled>false</enabled>
,因为它打破了DAG)
break
和这段代码:
implicit class ExtendedDataFrame(val df : DataFrame) extends AnyVal {
def break(name: String = ""):DataFrame = {
if (name.nonEmpty) {
println(s"About to break DAG for $name")
}
val cached = df.cache()
cached.count
cached
}
}
将如下所示:
df
.map(...)
.map(...)
.map(...)
.map(...)
.action
现在,当您的代码失败时,您将在spark UI中看到确切的行,并且在日志中您将看到在失败之前将要发生的转换。
答案 1 :(得分:2)
我也会检查查询的物理计划,也可能是RDD血统。
使用explain
了解实际计划(或df.queryExecution.sparkPlan
)以及将要执行的内容。
RDD沿袭可以使用RDD.toDebugString
(您可以使用df.rdd
访问),它将显示阶段和分区(=任务)。
有了这个,我注册SparkListener并开始收听SparkListenerStageSubmitted
和SparkListenerStageCompleted
个事件。聆听SparkListenerTaskStart
和SparkListenerTaskEnd
也很有帮助。
所有这些都能让你很好地了解什么时候完成或不完成。没有代码审查,更改,重新编译或类似。很干净。
使用SparkListener
Spark属性:
spark.extraListeners
应注册的Spark侦听器的完全限定类名的逗号分隔列表(初始化
SparkContext
时)。
请参阅Spark Listeners — Intercepting Events from Spark Scheduler。