如何在不知道作业ID的情况下获得Apache Spark工作进度?

时间:2015-10-29 17:16:32

标签: apache-spark

我有以下作为例子:

val sc: SparkContext // An existing SparkContext.
val sqlContext = new org.apache.spark.sql.SQLContext(sc)

val df = sqlContext.read.json("examples/src/main/resources/people.json")

df.count

我知道我可以使用spark上下文监视作业:然而,这给了我所有工作的事件(我不能使用,因为我不知道工作ID)。

如何才能获得“计数”操作的进度?

1 个答案:

答案 0 :(得分:0)

正如评论中已经建议的那样,可以使用REST API of the Spark UI来收集所需的数字。

主要问题是识别您所关注的阶段。从代码到阶段没有1:1的映射。例如,单个计数将触发两个阶段(一个阶段用于计算数据帧的每个分区中的元素,另一个阶段用于汇总第一阶段的结果)。阶段通常会获得触发其执行的操作的名称,尽管这可能是changed within the code

可以创建一个方法,使用特定名称查询所有阶段的REST API,然后将这些阶段的所有任务的数量以及已完成任务的数量相加。假设所有任务将大致采用相似的执行时间(如果数据集具有偏斜分区,则该假设为假)可以使用已完成任务的共享作为作业进度的度量。

def countTasks(sparkUiUrl: String, stageName: String): (Int, Int) = {
  import scala.util.parsing.json._
  import scala.collection.mutable.ListBuffer
  def get(url: String) = scala.io.Source.fromURL(url).mkString

  //get the ids of all running applications and collect them in a ListBuffer
  val applications = JSON.parseFull(get(sparkUiUrl + "/api/v1/applications?staus=running"))
  val apps: ListBuffer[String] = new scala.collection.mutable.ListBuffer[String]
  applications match {
    case Some(l: List[Map[String, String]]) => l.foreach(apps += _ ("id"))
    case other => println("Unknown data structure while reading applications: " + other)
  }

  var countTasks: Int = 0;
  var countCompletedTasks: Int = 0;

  //get the stages for each application and sum up the number of tasks for each stage with the requested name
  apps.foreach(app => {
    val stages = JSON.parseFull(get(sparkUiUrl + "/api/v1/applications/" + app + "/stages"))
    stages match {
      case Some(l: List[Map[String, Any]]) => l.foreach(m => {
        if (m("name") == stageName) {
          countTasks += m("numTasks").asInstanceOf[Double].toInt
          countCompletedTasks += m("numCompleteTasks").asInstanceOf[Double].toInt
        }
      })
      case other => println("Unknown data structure while reading stages: " + other)
    }
  })

  //println(countCompletedTasks + " of " + countTasks + " tasks completed")
  (countTasks, countCompletedTasks)
}

为给定的计数示例调用此函数

println(countTasks("http://localhost:4040", "show at CountExample.scala:16"))

将打印出两个数字:第一个将是所有任务的数量,第二个将是已完成任务的数量。

我已经使用Spark 2.3.0测试了这段代码。在生产环境中使用它之前,肯定需要一些额外的抛光,特别是一些更复杂的错误检查。不仅可以计算完成的任务,还可以计算失败的任务,从而提高统计数据。