1.关于Window
1.1Window概述
Windows are at the heart of processing infinite streams. Windows split the stream into “buckets” of finite size, over which we can applycomputations.
从官网的翻译来看意思为:窗口是处理无限流的核心。Windows将流拆分为大小有限的“bucket”,我们可以将其应用于计算。
1.2Window的类型
关于Window的可以分成两类:
1.CountWindow:按照指定的数据条数生成一个Window,与时间无关。
2. TimeWindow:按照时间生成Window。
对于TimeWindow,可以根据窗口实现原理的不同分成三类:滚动窗口(Tumbling Window)、滑动窗口(Sliding Window)和会话窗口(Session Window)。
1.2.1关于TimeWindow的详细描述
1.滚动窗口:将数据依据固定的窗口长度对数据进行切片(在本质上它是属于一种特殊的滑动窗口)。
特点:时间对齐,窗口长度固定,没有重叠
2.滑动窗口: 滑动窗口是固定窗口的更广义的一种形式,滑动窗口由固定的窗口长度和滑动间隔(即滑动步长)组成。
特点:时间对齐,窗口长度固定,可以有重叠
3.会话窗口:由一系列事件组合一个指定时间长度的timeout间隙组成,类似于web应用的session,也就是一段时间没有接收到新数据就会生成新的窗口。
特点:时间无对齐。
1.2.2关于窗口式Flink程序
1.keyed-stream:
stream
.keyBy(...) <- keyed versus non-keyed windows
.window(...) <- required: "assigner"
[.trigger(...)] <- optional: "trigger" (else default trigger)
[.evictor(...)] <- optional: "evictor" (else no evictor)
[.allowedLateness(...)] <- optional: "lateness" (else zero)
[.sideOutputLateData(...)] <- optional: "output tag" (else no side output for late data)
.reduce/aggregate/fold/apply() <- required: "function"
[.getSideOutput(...)] <- optional: "output tag"
2.no keyed-stream:
stream
.windowAll(...) <- required: "assigner"
[.trigger(...)] <- optional: "trigger" (else default trigger)
[.evictor(...)] <- optional: "evictor" (else no evictor)
[.allowedLateness(...)] <- optional: "lateness" (else zero)
[.sideOutputLateData(...)] <- optional: "output tag" (else no side output for late data)
.reduce/aggregate/fold/apply() <- required: "function"
[.getSideOutput(...)] <- optional: "output tag"
注意一般情况下我们都是将DataStream转换为KeyedStream在进行相应的计算,no keyed-stream用的相对较少 。
1.3WindowAPI测试
需求:每隔60s计算各个温度计中温度的最小值,并输出最新的时间戳
package com.mo.apiTest
import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.assigners.{
EventTimeSessionWindows, SlidingEventTimeWindows, TumblingEventTimeWindows}
import org.apache.flink.streaming.api.windowing.time.Time
case class thermometer(id : String ,time :String,Temp : Double)
//温度计样例类
object Time_window {
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
//从socket文本流中读取数据
val inputStream = env.socketTextStream("hadoop102",7777)
// 先转换成样例类类型
val dataStream = inputStream
.map( data => {
val arr = data.split(",")
thermometer(arr(0), arr(1), arr(2).toDouble)
} )
val res = dataStream
.map(data => (data.id,data.Temp,data.time))
.keyBy(_._1) //按照id进行分组
// .window(TumblingEventTimeWindows.of(Time.seconds(15))) 底层滚动窗口的实现
// .window(SlidingEventTimeWindows.of(Time.seconds(15),Time.milliseconds(3))) //底层滑动窗口的实现
// .window(EventTimeSessionWindows.withGap(Time.seconds(15))) 会话窗口
// .countWindow(10) 滚动计数窗口
// .countWindow(10,2) 滑动计数窗口
.timeWindow(Time.seconds(60)) //使用Flink为我们封装好的滑动或者滚动窗口的实现方法
.reduce((currdata,newdata)=>(currdata._1,currdata._2.min(newdata._2),newdata._3)) //每60s求出当前时间下各个温度计的最小值,并更新当前最新的时间戳
res.print()
env.execute("Tumblingwindow test")
}
}
运行截图:
可以看到此时输出的都是每隔60s内每种温度计的最小温度值和当前最新的时间戳