Scala EventTime窗口未启动

Scala EventTime窗口未启动,scala,apache-flink,flink-streaming,Scala,Apache Flink,Flink Streaming,我正在尝试使用EventTime设置流媒体解决方案。我将从卡夫卡消费。我的数据可能最多延迟一分钟(因此我的水印延迟一分钟)并且出现故障。我有30秒的视窗。我有以下设置: 卡夫卡消费量 object KafkaConsumer { def main(args: Array[String]) { val env = StreamExecutionEnvironment.getExecutionEnvironment env.setStreamTimeCharacteristic(

我正在尝试使用
EventTime
设置流媒体解决方案。我将从卡夫卡消费。我的数据可能最多延迟一分钟(因此我的水印延迟一分钟)并且出现故障。我有30秒的视窗。我有以下设置:

卡夫卡消费量

object KafkaConsumer {
  def main(args: Array[String]) {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
    val properties = getServerProperties
    val consumer = new FlinkKafkaConsumer010[ObjectNode](getKafkaTopic, new JsonNodeDeserializationSchema, properties)
    consumer.setStartFromGroupOffsets()

    val stream = env.addSource(consumer)
      .assignTimestampsAndWatermarks(new WMAssigner)

    stream
      .keyBy { jsonEvent =>
        val key = jsonEvent.findValue("key").toString replaceAll("\"","")
        key.toString
      }
      .window(TumblingEventTimeWindows.of(Time.seconds(30)))
      .process { new SessionWindowProcessor }
      .print
    env.execute("EventTime Test")
  }
}
WMAssigner.scala

class WMAssigner extends AssignerWithPeriodicWatermarks[ObjectNode] {

  var currentMaxTimestamp: Long = 0
  var currentWaterMark: Long = 0

  override def extractTimestamp(element: ObjectNode, previousElementTimestamp: Long): Long = {
    val lStr = element.findValue("ts").toString replaceAll("\"", "")
    currentMaxTimestamp = if(currentMaxTimestamp > lStr.toLong) currentMaxTimestamp else lStr.toLong
    currentMaxTimestamp
  }

  override def getCurrentWatermark: Watermark = {
      currentWaterMark = if(currentMaxTimestamp - 60000 < 0) 0 else currentMaxTimestamp - 60000
      new Watermark(currentWaterMark)

  }
}
样本数据:

"{\"ts\": 0,     \"key\": \"a\", \"value\": 0}",
"{\"ts\": 15000, \"key\": \"a\", \"value\": 1}",
"{\"ts\": 30000, \"key\": \"a\", \"value\": 2}",
"{\"ts\": 90001, \"key\": \"a\", \"value\": 3}" 

我希望在第四条消息出现后,我的第一个窗口会触发,值为
1
2
(我现在不确定包含是如何工作的)。不幸的是,我甚至没有看到
SessionWindowProcessor.scala
中的
println
。是否有什么地方我做错了,导致我的窗口设置失败?

您的Kafka主题有多少个分区?如果它有多个分区,问题是Flink必须为每个分区看到一个超过
90000
的时间戳,才能发出一个值为
30000
的水印。因此,您必须添加更多的数据,以便每个分区都有一个时间戳大于
90000
的元素,或者将Kafka主题的分区数设置为
1
。以下是有关的更多信息。

您的卡夫卡主题有多少个分区?如果它有多个分区,问题是Flink必须为每个分区看到一个超过
90000
的时间戳,才能发出一个值为
30000
的水印。因此,您必须添加更多的数据,以便每个分区都有一个时间戳大于
90000
的元素,或者将Kafka主题的分区数设置为
1
。下面是有关的一些详细信息。

要了解它的价值,您的
extractTimestamp()
方法应该返回lStr.toLong,而不是currentMaxTimestamp。这种方法跟踪currentMaxTimestamp是有意义的,这样值就可以用于生成水印,但是extractTimestamp的作用是为每个流元素提供Flink事件时间戳

但是,我不相信这可以解释为什么您没有看到任何输出——如果您的数据实际上是按时间戳排序的,当然不是,如示例中所示


还请注意,您可能正在使用一个更易于使用的方法。

值得一提的是,您的
extractTimestamp()
方法应该返回lStr.toLong,而不是currentMaxTimestamp。这种方法跟踪currentMaxTimestamp是有意义的,这样值就可以用于生成水印,但是extractTimestamp的作用是为每个流元素提供Flink事件时间戳

但是,我不相信这可以解释为什么您没有看到任何输出——如果您的数据实际上是按时间戳排序的,当然不是,如示例中所示


还请注意,您可以使用一个更简单的分区。

Kafka主题位于单个分区上,但这对于我将来扩展此分区是一个很好的信息,谢谢。David的答案实际上是我问题的解决方案。Kafka主题是在一个分区上,但这是一个很好的信息,可供我将来扩展时参考,谢谢。David的回答实际上是我问题的解决方案。实际上是
extractTimestamp
没有返回
lStr
,因为某种原因,一旦我返回
lStr.toLong
它就按预期工作了。我确实采纳了您的建议,使用了
BoundedAutofordernessTimestampExtractor
,正如您所说,这是一个更简单的实现,非常感谢!实际上是
extractTimestamp
没有返回
lStr
,因为某种原因,一旦我返回
lStr.toLong
它就按预期工作了。我确实采纳了您的建议,使用了
BoundedAutofordernessTimestampExtractor
,正如您所说,这是一个更简单的实现,非常感谢!
"{\"ts\": 0,     \"key\": \"a\", \"value\": 0}",
"{\"ts\": 15000, \"key\": \"a\", \"value\": 1}",
"{\"ts\": 30000, \"key\": \"a\", \"value\": 2}",
"{\"ts\": 90001, \"key\": \"a\", \"value\": 3}"