Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 为什么在流媒体源中未获得任何新偏移量的情况下触发新批处理?_Apache Spark_Spark Streaming_Spark Structured Streaming_Spark Streaming Kafka - Fatal编程技术网

Apache spark 为什么在流媒体源中未获得任何新偏移量的情况下触发新批处理?

Apache spark 为什么在流媒体源中未获得任何新偏移量的情况下触发新批处理?,apache-spark,spark-streaming,spark-structured-streaming,spark-streaming-kafka,Apache Spark,Spark Streaming,Spark Structured Streaming,Spark Streaming Kafka,我有多个spark结构化流媒体作业,我看到的通常行为是,只有当Kafka中有任何新的偏移量(用作创建流媒体查询的源)时,才会触发新的批处理 但当我运行使用mapGroupsWithState演示任意有状态操作的示例时,我发现即使流源中没有新数据,也会触发一个新批处理。为什么会这样?可以避免吗 更新-1 我修改了上面的示例代码并删除了与状态相关的操作,比如更新/删除它。函数只输出零。但是,在netcat服务器上没有任何新数据的情况下,仍然会每10秒触发一次批处理 import java.sql.T

我有多个spark结构化流媒体作业,我看到的通常行为是,只有当Kafka中有任何新的偏移量(用作创建流媒体查询的源)时,才会触发新的批处理

但当我运行使用
mapGroupsWithState
演示任意有状态操作的示例时,我发现即使流源中没有新数据,也会触发一个新批处理。为什么会这样?可以避免吗

更新-1 我修改了上面的示例代码并删除了与状态相关的操作,比如更新/删除它。函数只输出零。但是,在netcat服务器上没有任何新数据的情况下,仍然会每10秒触发一次批处理

import java.sql.Timestamp

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.streaming._

object Stateful {

  def main(args: Array[String]): Unit = {

    val host = "localhost"
    val port = "9999"

    val spark = SparkSession
      .builder
      .appName("StructuredSessionization")
      .master("local[2]")
      .getOrCreate()

    import spark.implicits._

    // Create DataFrame representing the stream of input lines from connection to host:port
    val lines = spark.readStream
      .format("socket")
      .option("host", host)
      .option("port", port)
      .option("includeTimestamp", true)
      .load()

    // Split the lines into words, treat words as sessionId of events
    val events = lines
      .as[(String, Timestamp)]
      .flatMap { case (line, timestamp) =>
        line.split(" ").map(word => Event(sessionId = word, timestamp))
      }

    val sessionUpdates = events
      .groupByKey(event => event.sessionId)
      .mapGroupsWithState[SessionInfo, Int](GroupStateTimeout.ProcessingTimeTimeout) {

        case (sessionId: String, events: Iterator[Event], state: GroupState[SessionInfo]) =>
          0
      }

    val query = sessionUpdates
      .writeStream
      .outputMode("update")
      .trigger(Trigger.ProcessingTime("10 seconds"))
      .format("console")
      .start()

    query.awaitTermination()
  }
}

case class Event(sessionId: String, timestamp: Timestamp)

case class SessionInfo(
                        numEvents: Int,
                        startTimestampMs: Long,
                        endTimestampMs: Long)

显示空批的原因是mapGroupsWithState调用中使用了超时

据《学习火花2.0》一书所述:

“下一个微批处理将调用此超时键上的函数,即使该微批处理中没有该键的数据。[…]由于超时是在微批处理期间处理的,因此它们的执行时间不精确,并且严重依赖于触发间隔[…]

由于您已将超时设置为
GroupStateTimeout.ProcessingTimeout
,因此它与您的查询触发时间(10秒)一致。另一种方法是根据事件时间设置超时(即
GroupStateTimeout.eventTimeTimeTimeout

上的ScalaDocs提供了更多详细信息:

当某个组发生超时时,将为该组调用该函数,但不包含任何值,并且GroupState.hastinmedout()设置为true


无论如何,即使卡夫卡中没有数据,也始终会触发批次0。如果kafka中没有新数据,则不应触发任何后续触发器。是的,但在本例中,即使流源中没有新数据,也会触发新批。不仅仅是批处理零,还有后续批处理。奇怪的是,你能粘贴你的代码样本吗?这和我在描述中提到的我正在尝试运行的示例是一样的。我错提了卡夫卡。流媒体源是netcat服务器。但以卡夫卡为源头,这与netcatI的行为相同,我认为这是因为触发。Mike,正如我提到的,只有在使用mapGroupWithState时才会观察到这种行为。否则,即使触发器已就位,也不会增加批次Id。批次仍然每10秒触发一次,但如果没有新数据,您将每10秒看到相同的批次Id。Spark版本为2.4.6可能我需要更好地表达问题,并具体描述情况。我所说的触发“新”批处理的意思是,在没有新数据的情况下,批处理id会增加。谢谢@mike。这是有道理的。如果你能更新你的答案,那么我可以接受它作为子孙后代的解决方案。