窗口操作如何与Flink中的keyBy一起使用?

时间:2017-07-04 02:52:46

标签: scala apache-flink flink-streaming

我在Kafka的数据看起来像这样:

{
  "account": "iOS", //Possible values: iOS, android, web, windows
  "events": [
    {
      "timestamp": "2017-07-03T20:19:35Z"
    }
  ]
}

时间戳从2017-07-03T20:19:35Z2017-07-03T20:22:30Z(约3分钟)。我有这个Flink程序从上面的kafka主题中提取数据:

object TestWindow {
  def main(args: Array[String]) = {
    val props = new Properties()
    props.put(...)

    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

    env.addSource(new FlinkKafkaConsumer010[String]("topic", new SimpleStringSchema(), props)).
      keyBy(jsonStr => {
        val jsonParser = new JsonParser()
        val jsonObject = jsonParser.parse(jsonStr).getAsJsonObject()
        jsonObject.get("account")
    }).window(TumblingEventTimeWindows.of(Time.seconds(10)))
      .reduce({(v1, v2) =>
        println(v1 + " " + v2)
        ""
      })
    env.execute()
  }
}

我无法理解窗口如何与keyBy操作一起使用。

我理解上面的keyBy操作会创建包含相同键元素的不同分区。但我很困惑何时创建窗口以及如何将每个分区添加到哪个窗口?

我的猜测是,当每个JSON对象到达时,它将被keyBy操作键入,然后基于该JSON对象的事件timeStamp,它将创建一个窗口10秒钟?

因此,例如,如果时间戳为"2017-07-03T20:19:35Z"的JSON对象到达且具有account类型的iOS,则将创建用于iOS的分区键,并且还将为{创建一个窗口{1}}到"2017-07-03T20:19:35Z"?或者是一个每10秒创建一个窗口,而不管来自Kafka的JSON对象的事件时间戳?

1 个答案:

答案 0 :(得分:2)

您对keyBy的假设是正确的。 keyBy在已定义的键属性上对流进行分区,并按键计算窗口。

您在示例中使用的TumblingEventTimeWindow具有固定的窗口边框,即边框不依赖于数据的时间戳。一个10秒的翻滚窗口将创建[00:00:00.000, 00:00:10.000)[00:00:10.000, 00:00:20.000)等窗口。到达窗口运算符的记录将分配给与其时间戳相交的窗口。当窗口关闭时(操作员的本地时间超过窗口的结束时间戳),计算并发出窗口的结果。请注意,窗口仅使用第一个记录进行实例化,即空窗口不会触发计算并且无法发出数据,例如零计数。

其他窗口类型(如会话窗口)具有数据驱动的边界。在会话窗口的情况下,所有不超过彼此相隔一定时间间隔的记录将被分组到一个窗口中。