awaitTermination后如何获取流式查询的进度?

时间:2019-01-30 09:04:50

标签: apache-spark spark-structured-streaming

我是Spark的新手,正在阅读一些有关监视Spark应用程序的内容。基本上,我想知道在给定的触发时间和查询进度下,spark应用程序处理了多少条记录。我知道'lastProgress'提供了所有这些指标,但是当我将awaitTermination与'lastProgress'一起使用时,它总是返回null。

 val q4s = spark.readStream
  .format("kafka")
  .option("kafka.bootstrap.servers", brokers)
  .option("subscribe", topic)
  .option("startingOffsets", "earliest")
  .load()
  .writeStream
  .outputMode("append")
  .option("checkpointLocation", checkpoint_loc)
  .trigger(Trigger.ProcessingTime("10 seconds"))
  .format("console")
  .start()

  println("Query Id: "+ q4s.id.toString())
  println("QUERY PROGRESS.........")
println(q4s.lastProgress);
q4s.awaitTermination();

输出:

Query Id: efd6bc15-f10c-4938-a1aa-c81fdb2b33e3
QUERY PROGRESS.........
null

使用awaitTermination时如何获得查询进度,或者如何不使用awaitTermination保持查询连续运行?

谢谢。

2 个答案:

答案 0 :(得分:1)

您必须引用要查询的流查询来启动一个单独的线程(例如q4s)并定期提取进度。

启动查询的线程(Spark结构化流应用程序的主线程)通常为awaitTermination,因此它启动的流查询的守护程序线程可以继续运行。

答案 1 :(得分:1)

使用专用的可运行线程

您可以创建一个专用线程来连续打印流式查询的最新进度。

首先,定义一个可运行的Monitoring类,该类每10秒(10000ms)输出一次最后的Progress:

class StreamingMonitor(q: StreamingQuery) extends Runnable {
  def run {
    while(true) {
      println("Time: " + Calendar.getInstance().getTime())
      println(q.lastProgress)
      Thread.sleep(10000)
    }
  }
}

第二,将其实现到您的应用程序代码中,如下所示:

val q4s: StreamingQuery = df.writeStream
  [...]
  .start()

new Thread(new StreamingMonitor(q4s)).start()

q4s.awaitTermination()

遍历查询状态

您还可以对查询状态进行while循环:

val q4s: StreamingQuery = df.writeStream
  [...]
  .start()

while(q4s.isActive) {
  println(q4s.lastProgress)
  Thread.sleep(10000)
}

q4s.awaitTermination()

使用StreamingQueryListener的替代解决方案

监视流查询的另一种方法是使用StreamingQueryListener。再次,首先定义一个扩展StreamingQueryListener的类:

import org.apache.spark.sql.streaming.{StreamingQueryListener, StreamingQueryProgress}
import org.apache.spark.sql.streaming.StreamingQueryListener.QueryProgressEvent


class MonitorListener extends StreamingQueryListener {

  override def onQueryStarted(event: StreamingQueryListener.QueryStartedEvent): Unit = { }

  override def onQueryProgress(event: QueryProgressEvent): Unit = {
    println(s"""numInputRows: ${event.progress.numInputRows}""")
    println(s"""processedRowsPerSecond: ${event.progress.processedRowsPerSecond}""")
  }

  override def onQueryTerminated(event: StreamingQueryListener.QueryTerminatedEvent): Unit = { }
}

然后在您的SparkSession中注册它:

spark.streams.addListener(new MonitorListener)