使用 Apache Spark UI 进行调试

本文概述了可用于速览 Apache Spark 应用程序内部信息的不同调试选项。 应注意以下三个重要地方:

  • Spark UI
  • 驱动程序日志
  • 执行程序日志

请参阅使用 Spark UI 诊断成本和性能问题,来逐步了解如何使用 Spark UI 诊断成本和性能问题。

Spark UI

启动作业后,Spark UI 会显示有关应用程序中发生的情况的信息。 若要转到 Spark UI,请单击附加的计算:

“流式处理”选项卡

进入 Spark UI 后,如果流式处理作业正在此计算中运行,则会显示“流式处理”选项卡。 如果此计算中没有正在运行的流式处理作业,此选项卡将不可见。 你可跳到驱动程序日志了解如何检查启动流式处理作业时可能发生的异常。

在此页中需要注意的第一件事是检查流式处理应用程序是否正在从你的源接收任何输入事件。 在本例中,你可看到该作业每秒接收 1000 个事件。

注意

对于 TextFileStream,由于文件是输入的,因此输入事件的数量始终为 0。 在这种情况下,可以查看笔记本中的已完成批处理部分,了解如何查找详细信息。

如果你有一个接收多个输入流的应用程序,则可单击“输入速率”链接,该链接将显示每个接收器接收的事件数。

处理时间

向下滚动,找到“处理时间”关系图。 这是了解流式处理作业性能的关键图之一。 一般来说,如果你可在批处理时间的 80% 内处理每个批,那就很好。

对于此应用程序,批处理时间间隔为 2 秒。 平均处理时间为 450 毫秒,大大低于批处理时间间隔。 如果平均处理时间接近或大于批处理时间间隔,则你的流式处理应用程序将开始排队,很快就会导致积压工作 (backlog),最终导致流式处理作业失败。

已完成的批处理

在页面末尾,你将看到所有已完成的批处理列表。 页面显示有关最近完成的 1000 个批处理的详细信息。 从表中,你可以获得每个批处理的事件数及其处理时间。 如果你想要详细了解某个批处理的情况,可单击该批处理链接进入“批处理详细信息”页。

“批处理详细信息”页

此页面包含你想要了解的有关批处理的所有详细信息。 两个关键事项:

  • 输入:包含有关批处理输入的详细信息。 在本例中,它包含有关 Apache Kafka 主题、Spark 结构化流式处理为此批处理读取的分区和偏移量的详细信息。 对于 TextFileStream,你将看到为此批处理读取的文件名列表。 对于从文本文件读取的流式处理应用程序,这是启动调试的最佳方式。
  • 处理:可以单击作业 ID 的链接,其中包含在此批处理期间完成的处理的所有相关详细信息。

“作业详细信息”页

作业详细信息页显示 DAG 可视化。 这对于了解每个批处理的操作顺序和依赖项非常有用。 在本例中,可以看到批处理从 Kafka 直接流读取输入,然后执行平面映射操作,最后执行映射操作。 然后通过 updateStateByKey,使用生成的流更新全局状态。 (灰色框表示已跳过的阶段。Spark 非常智能,如果某些阶段不需要重新计算,则会跳过它们。如果该数据已设置检查点或已缓存,Spark 不会重新计算这些阶段。在本例中,由于 updateStateBykey,这些阶段相应地依赖于以前的批处理。由于 Spark 结构化流式处理会在流内部设置检查点,并且它会从检查点读取而不是依赖于以前的批处理,因此它们显示为灰色阶段。)

在页面底部,还可找到为此批处理执行的作业列表。 可以单击说明中的链接,以深入了解任务级别的执行。

“任务详细信息”页

对于 Spark 应用程序,这是可从 Spark UI 获取的最精细调试级别。 此页面包含为此批处理执行的所有任务。 如果你正在调查流式处理应用程序的性能问题,此页会提供一些信息,例如已执行的任务数及其执行位置(在哪个执行程序上)、随机信息等

提示

请确保任务在计算中的多个执行程序(节点)上执行,以便在处理时具有足够的并行度。 如果你只有一个接收器,可能有时只有一个执行器来执行所有工作,尽管计算中有多个执行器。

线程转储

线程转储显示 JVM 线程状态的快照。

在调试特定挂起或运行缓慢的任务时,线程转储很有用。 若要在 Spark UI 中查看特定任务的线程转储:

  1. 单击“作业”选项卡。
  2. 在“作业”表中,找到与要查看的线程转储对应的目标作业,然后单击“说明”列中的链接。
  3. 在作业的“阶段”表中,找到与要查看的线程转储对应的目标阶段,然后单击“说明”列中的链接。
  4. 在阶段的“任务”列表中,找到与要查看的线程转储对应的目标任务,并记下其“任务 ID”和“执行程序 ID”。
  5. 单击“执行程序”选项卡。
  6. 在“执行程序”表中,找到包含与之前记下的“执行程序 ID”值对应的“执行程序 ID”值的行。 在该行中,单击“线程转储”列中的链接。
  7. 在“执行程序的线程转储”表中,单击“线程名称”列包含 (TID) 的行,后跟前面记下的“任务 ID”值。 (如果任务已完成运行,则找不到匹配的线程)。 显示任务的线程转储。

对于调试驱动程序似乎挂起(例如,没有显示 Spark 进度条)或查询没有进展(例如,Spark 进度条停滞在 100%)的问题,线程转储也很有用。 若要在 Spark UI 中查看驱动程序的线程转储:

  1. 单击“执行程序”选项卡。
  2. 在“执行程序”表的“驱动程序”行中,单击“线程转储”列中的链接。 显示驱动程序的线程转储。

驱动程序日志

驱动程序日志有以下 2 个用途:

  • 异常:有时,Spark UI 中可能未显示“流式处理”选项卡。 这是因为流式处理作业由于某些异常而未启动。 你可以深入驱动程序日志,查看异常的堆栈跟踪。 在某些情况下,流式处理作业可能已正常启动。 但你会发现所有批处理永远不会转到“已完成的批处理”部分。 它们可能都处于“正在处理”或“已失败”状态。 在这种情况下,借助驱动程序日志,可以很方便地了解基本问题的性质。
  • Print:作为 DAG 一部分的任何 print 语句也会显示在日志中。

执行程序日志

如果发现某些任务行为异常,并且想要查看特定任务的日志,则执行程序日志有时会很有帮助。 在上面所示的“任务详细信息”页中,可以获取运行任务的执行程序。 在获得该程序后,可转到计算 UI 页面,单击 # 节点,然后单击主节点。 主节点页会列出所有工作节点。 可选择运行可疑任务的工作节点,然后转到 log4j 输出。