在流式计算中,我们所接入的数据集是无限流,或者说是没有边界的数据流。那么有没有办法将无限流转换为有限流呢?这里就需要引入 Window(窗口)的概念,通过 Window 我们可以按照固定时间或长度将无限数据流切分成不同长度的有限数据块,然后在每个窗口内针对数据块进行聚合运算。
Window 分类
Keyed Window 和 Global Window
Time Window 和 Count Window
Window API
Time Window 和 Count Window
Time Window
基于时间定义的窗口。根据不同业务场景又可以分为滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)和会话窗口(Session Window)三种。
滚动窗口(Tumbing Window):
滚动窗口是按照固定时间进行切分,而且所有窗口之间的数据不会重叠,使用时只需要指定一个窗口长度即可。
从上面的示例图中可以看到,滚动窗口的窗口大小(window size)是固定的,而且相邻窗口之间是连续的。现在有这样的业务场:某公司要求每 10 秒统计一次最近 10 秒内各个电商平台的订单数量并输出到大屏幕,这时候就需要用到滚动窗口了,我们只需要将窗口大小设置为 10 秒就可以。我们使用 netcat 发送 Socket 数据来模拟订单流量。
在 com.xxx.window 包下创建 TumblingWindow Scala Object,代码如下:
package com.xxx.window
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.time.Time
object TumblingWindow {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
val textDstream: DataStream[String] = env.socketTextStream("localhost", 9999)
import org.apache.flink.streaming.api.scala._
val dataStream: DataStream[(String, Int)] = textDstream
.filter(_.nonEmpty)
.map((_, 1))
.keyBy(0) // 按照第0个字段分组
.timeWindow(Time.seconds(10)) // 设定窗口大小
.sum(1) // 对第1个字段求和
dataStream.print().setParallelism(1)
env.execute("Tumbling Window")
}
}
在上面的代码中,我们监听了 localhost 的 9999 端口,将接收到的