有没有办法动态停止Spark结构化流传输?

时间:2018-09-25 12:48:43

标签: apache-spark apache-kafka spark-streaming spark-structured-streaming

在我的场景中,我不时有几个dataSet,我需要将它们吸收到我们的平台中。摄取过程涉及几个转换步骤。其中之一就是Spark。到目前为止,我尤其使用Spark结构化流。基础结构还涉及kafka,spark结构化流从中读取数据。

我想知道是否有一种方法可以在一段时间内检测何时没有其他东西要消耗某个主题来决定停止工作。那就是我想在消耗该特定数据集然后停止它之前花时间运行它。出于特定原因,我们决定不使用spark的批处理版本。

因此,是否存在任何超时或可用于检测没有更多数据传入并且所有内容均已处理的事件。

谢谢

3 个答案:

答案 0 :(得分:2)

提出了一些建议:

  1. 正如@Michael West所指出的那样,有许多听众来跟踪进度
  2. 从我收集的内容来看,结构化流式doesn't yet support graceful shutdown

因此,一种选择是定期检查查询活动,根据可配置状态(当您确定无法/不应取得进一步进展时)动态 关闭:

// where you configure your spark job...
spark.streams.addListener(shutdownListener(spark))

// your job code starts here by calling "start()" on the stream...

// periodically await termination, checking for your shutdown state
while(!spark.sparkContext.isStopped) {
  if (shutdown) {
    println(s"Shutting down since first batch has completed...")
    spark.streams.active.foreach(_.stop())
    spark.stop()
  } else {
    // wait 10 seconds before checking again if work is complete
    spark.streams.awaitAnyTermination(10000)
  }
}

您的侦听器可以通过多种方式动态关闭。例如,如果您只等待一个批次,则在第一次更新后就关闭:

var shutdown = false
def shutdownListener(spark: SparkSession) = new StreamingQueryListener() {
  override def onQueryStarted(_: QueryStartedEvent): Unit = println("Query started: " + queryStarted.id)
  override def onQueryTerminated(_: QueryTerminatedEvent): Unit = println("Query terminated! " + queryTerminated.id)
  override def onQueryProgress(_: QueryProgressEvent): Unit = shutdown = true
}

或者,如果您需要在更复杂的状态更改后关闭,则可以解析queryProgress.progress的json主体,以确定是否在给定的onQueryUpdate事件触发时关闭。

答案 1 :(得分:1)

Structured Streaming Monitoring Options

您可以使用query.lastProgress获取时间戳并围绕该时间戳构建逻辑。不要忘记将检查点保存到持久,持久的可用商店中。

答案 2 :(得分:1)

您可能可以使用:-

def stopStreamQuery(query: StreamingQuery, awaitTerminationTimeMs: Long) {
    while (query.isActive) {
      try{
        if(query.lastProgress.numInputRows < 10){
          query.awaitTermination(1000)
        }
      }
      catch
      {
        case e:NullPointerException => println("First Batch")
      }
      Thread.sleep(500)
    }
  }

您可以创建一个numInputRows变量。