我有以下作为例子:
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)。
如何才能获得“计数”操作的进度?
答案 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测试了这段代码。在生产环境中使用它之前,肯定需要一些额外的抛光,特别是一些更复杂的错误检查。不仅可以计算完成的任务,还可以计算失败的任务,从而提高统计数据。