首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当水印小于窗口结束时,触发基于事件时间的Flink窗口操作。

当水印小于窗口结束时,触发基于事件时间的Flink窗口操作。
EN

Stack Overflow用户
提问于 2018-11-30 03:31:07
回答 1查看 142关注 0票数 0

我正在测试事件-时间和水印在Flink.下面是我的密码。

代码语言:javascript
复制
object WatermarkTest {

     def main(args: Array[String]): Unit = {
         val env = StreamExecutionEnvironment.getExecutionEnvironment
         env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

         val properties = new Properties()
         properties.setProperty("bootstrap.servers", "127.0.0.1:9092")
         properties.setProperty("group.id", "enven-test")

         env.getConfig.setAutoWatermarkInterval(1L)
         val input = env.addSource(new FlinkKafkaConsumer011[String]("event-time-topic", new SimpleStringSchema(), properties))

         val inputMap = input.map(f=> {
           val arr = f.split(",")
           val code = arr(0)
           val time = arr(1).toLong
           MyEvent(code, time)
        })

        val watermark = inputMap.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessGenerator())
        val window = watermark
           .keyBy(_.code)
           .window(TumblingEventTimeWindows.of(Time.seconds(5)))
           .apply(new WindowFunctionTest)

        window.print()

       env.execute()
    }

   class WindowFunctionTest extends WindowFunction[MyEvent,(String, Int,String,String,String,String),String,TimeWindow]{
       override def apply(key: String, window: TimeWindow, input: Iterable[MyEvent], out: Collector[(String, Int,String,String,String,String)]): Unit = {
       val list = input.toList.sortBy(_.time)
       val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
 out.collect(key,input.size,format.format(list.head.time),format.format(list.last.time),format.format(window.getStart),format.format(window.getEnd))
    }
  }
}

下面是事件时间和水印生成器:

代码语言:javascript
复制
class BoundedOutOfOrdernessGenerator extends 
      AssignerWithPeriodicWatermarks[MyEvent] {
      val maxOutOfOrderness = 10000L

      var currentMaxTimestamp: Long = _

      val format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")

      var watermark: Watermark = null
      var timestamp: Long = _

      override def extractTimestamp(element: MyEvent, previousElementTimestamp: Long): Long = {
           timestamp = element.time
           currentMaxTimestamp = if (timestamp > currentMaxTimestamp) timestamp else currentMaxTimestamp
           println("timestamp:" + element.code +","+ element.time + "|" +format.format(element.time) +", currentMaxTimestamp: "+  currentMaxTimestamp + "|"+ format.format(currentMaxTimestamp) + ", watermark: "+ format.format(watermark.getTimestamp))
           timestamp;
      }

      override def getCurrentWatermark(): Watermark = {
           watermark = new Watermark((currentMaxTimestamp - maxOutOfOrderness)/1000*1000);
          watermark
      }
 }

这是一些测试数据。在我看来,第一次计算后应该水印: 2016-04-27 19:34:25.000.测试结果表明水印后触发的计算值为: 2016-04-27 19:34:24.000。有人能解释一下吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-30 19:50:28

我建议您在getCurrentWatermark和extractTimestamp中打印水印。这应该能说明到底发生了什么。

问题是,extractTimestamp被调用从事件中提取时间戳,时间戳为19:34:35 --该事件将导致当前水印提前到19:34:25,从而触发窗口--此时您正在打印当前水印。在执行extractTimestamp中的println时,水印尚未提前以反映这一新事件。但是在extractTimestamp返回后不久,getCurrentWatermark将被调用,这将将当前水印提升到19:34:25,这将触发窗口。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53550831

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档