如何从程序获得火花工作状态?

时间:2014-11-27 07:24:06

标签: hadoop apache-spark

我知道hadoop REST API可以通过程序访问作业状态。

同样有什么方法可以在程序中获得spark作业状态吗?

5 个答案:

答案 0 :(得分:4)

它与REST API不相似,但您可以通过向SparkContext.addSparkListener注册SparkListener来跟踪应用程序内部的作业状态。它是这样的:

sc.addSparkListener(new SparkListener {
  override def onStageCompleted(event: SparkListenerStageCompleted) = {
    if (event.stageInfo.stageId == myStage) {
      println(s"Stage $myStage is done.")
    }
  }
})

答案 1 :(得分:2)

有一个(n)(几乎)未记录的REST API功能,几乎可以提供您在Spark UI上看到的所有内容:

http://<sparkMasterHost>:<uiPort>/api/v1/...

对于本地安装,您可以从这里开始:

http://localhost:8080/api/v1/applications

您可以在此处找到可能的终点:https://github.com/apache/spark/blob/master/core/src/main/scala/org/apache/spark/status/api/v1/ApiRootResource.scala

答案 2 :(得分:1)

您也可以在不使用Spark Job History服务器的情况下获得Spark作业状态。您可以使用SparkLauncher 2.0.1(甚至Spark 1.6版本也可以)从Java程序启动Spark作业:

SparkAppHandle appHandle = sparkLauncher.startApplication();

您还可以将侦听器添加到startApplication()方法:

SparkAppHandle appHandle = sparkLauncher.startApplication(sparkAppListener);

侦听器有2个方法可以告知您有关工作状态更改和信息更改的信息。

我使用CountDownLatch实现,它按预期工作。这适用于SparkLauncher 2.0.1版,它也适用于Yarn-cluster模式。

   ...
final CountDownLatch countDownLatch = new CountDownLatch(1);
SparkAppListener sparkAppListener = new SparkAppListener(countDownLatch);
SparkAppHandle appHandle = sparkLauncher.startApplication(sparkAppListener);
Thread sparkAppListenerThread = new Thread(sparkAppListener);
sparkAppListenerThread.start();
long timeout = 120;
countDownLatch.await(timeout, TimeUnit.SECONDS);    
    ...

private static class SparkAppListener implements SparkAppHandle.Listener, Runnable {
    private static final Log log = LogFactory.getLog(SparkAppListener.class);
    private final CountDownLatch countDownLatch;
    public SparkAppListener(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
    @Override
    public void stateChanged(SparkAppHandle handle) {
        String sparkAppId = handle.getAppId();
        State appState = handle.getState();
        if (sparkAppId != null) {
            log.info("Spark job with app id: " + sparkAppId + ",\t State changed to: " + appState + " - "
                    + SPARK_STATE_MSG.get(appState));
        } else {
            log.info("Spark job's state changed to: " + appState + " - " + SPARK_STATE_MSG.get(appState));
        }
        if (appState != null && appState.isFinal()) {
            countDownLatch.countDown();
        }
    }
    @Override
    public void infoChanged(SparkAppHandle handle) {}
    @Override
    public void run() {}
}

答案 3 :(得分:1)

提供Java的答案。在Scala中,仅使用SparkContext而不是JavaSparkContext几乎是相似的。

假设您有一个JavaSparkContext:

private final JavaSparkContext sc;

以下代码允许从“工作和阶段”标签获取所有可用信息:

JavaSparkStatusTracker statusTracker = sc.statusTracker();
for(int jobId: statusTracker.getActiveJobIds()) {
     SparkJobInfo jobInfo = statusTracker.getJobInfo(jobId);
     log.info("Job " + jobId + " status is " + jobInfo.status().name());
     log.info("Stages status:");

     for(int stageId: jobInfo.stageIds()) {
         SparkStageInfo stageInfo = statusTracker.getStageInfo(stageId);

         log.info("Stage id=" + stageId + "; name = " + stageInfo.name()
                    + "; completed tasks:" + stageInfo.numCompletedTasks()
                    + "; active tasks: " + stageInfo.numActiveTasks()
                    + "; all tasks: " + stageInfo.numTasks()
                    + "; submission time: " + stageInfo.submissionTime());
    }
}

不幸的是,其他所有内容只能从scala Spark Context访问,因此使用Java提供的结构可能会有些困难。

池列表: sc.sc()。getAllPools()

执行器内存状态: sc.sc()。getExecutorMemoryStatus()

执行者ID: sc.sc()。getExecutorIds()

存储信息: sc.sc()。getRddStorageInfo()

...您可以尝试在其中找到更多有用的信息。

答案 4 :(得分:0)

Spark UI上有(n)(几乎)未记录的REST API功能,可提供有关作业和性能的指标。

您可以通过以下方式访问它:

http://<driverHost>:<uiPort>/metrics/json/

(UIPort默认为4040)