前篇中,我们已经初略讲解了Flink中的数量窗口与时间窗口。
无论是哪一种窗口,他们的作用都类似于计算器(计算数量、时间)仅仅只是让数据堆积(不会像默认的流处理,来一条处理一条),只有当满足触发计算时机的时候,便开始计算,比如五个数据才计算,或者五秒钟才计算一次…
数量窗口的核心,便是数量的定义,当我们数据达到定义的量时,便会触发窗口计算逻辑
那么数量窗口究竟如何使用呢?哎,让我们来一探究竟!
我们首先还是回顾下Flink计算程序步骤
获取执行环境
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setRuntimeMode(RuntimeExecutionMode.STREAMING);
env.setParallelism(1);
加载数据源
DataStreamSource<Location> locationSource = env.addSource(new LocationSource())
数据转换处理
//todo 我们这里,数据转换就使用CountWindow
数据输出
// 例如输出到mysql
result.addSink(new MysqlSink());
// 例如输出到控制台
result.print();
执行
env.execute("count-window");
窗口使用前提:
在使用窗口前,我们必须要确保已经有了数据源
根据选择是否使用KeyBy算子(后边会讲)
我们直接使用我们的数据源来调用Window API
即可
ex:
source.countWindow(一个窗口容纳数据数量);
返回值,返回了一个WindowedStream
类型的数据流.
这步代码仅表示此计算程序使用的是CountWindow,且窗口的大小为1,如此设置,那么每来一个数据触发一次窗口计算,设置为2,则每相同的KEY出现两次,才会执行对应数据窗口计算(正如上方所说,起到了一个计算器的作用,那么我这里则是一个数据触发一次计算时机)
但需要注意,这里窗口并不涉及到计算逻辑!!!!!!
上边,我们的窗口已经拿到了数据了,拿到窗口后的数据,如何触发计算呢?
如果需要窗口中执行逻辑,我们要调用apply
算子;apply
算子,必须作用在WindowedStream
ex:
DataStream<T> result = windowedStream.apply(算子逻辑实现);
我们使用IDEA 参数提示,来看下我们的的apply
算子究竟需要什么参数
查阅发现,WindowFunction
是一个接口,其中还有一个apply
抽象方法
IN:入参
OUT:出参
KEY:当前窗口数据的唯一键 (即前边代码的keyBy(Location::getVehicleId)
操作)
W:可以应用此窗口功能的Window的类型
WindowFunction
呢,又有着如下一些实现类
实际上呢,我们的windowedStream.apply()
方法,本质是调用的 WindowFunction或其实现类
中的apply()
,为我们做的数据处理.
故此,根据参数提示,我们直接New 一个``WindowFunction` 的匿名内部类试一试
参数详解:
key: 上方代码 .keyBy(Location::getVehicleId) 实质就是Location对象中的VehicleId
window: 当前可用窗口类型 GlobalWindow
input: 入参数据 Location泛型的迭代器,数量嘛,自然就是窗口设置的大小了,如果是count 窗口则是count中指定的数量;如果是Time ,则是规定时间内的实际数据数量
out: 出参数据, 计算结果后什么类型;Collector 负责吧参数收集输出
示例:将我们的Location 使用CountWindow转换为JSON字符串
Collector 收集后,就得到了上图示例返回值DataStream
,我们把他是作为计算结果,输出看一看
如果不想写匿名内部类这种方式,我们也可以自定义类去实现 WindowFunction
或继承WindowFunction的实现类
ex:
public static class SpeedAlarmWindow extends RichWindowFunction<Location, String, Integer, GlobalWindow> {}
特别说明,实际开发中,继承RichWindowFunction
实现我们自己的方法是最优解
RichWindowFunction
自己继承自AbstractRichFunction
且实现了WindowFunction
AbstractRichFunction
中的五个方法非常核心,getRuntimeContext()
方法可以拿到当前计算程序运行上下文环境,这个在以后的复杂逻辑开发特别有用。且还有open()、close()
方法,与最开始讲解的自定义数据源与自定义Sink一样,其在整个计算job中 只开启一次,或者只关闭一次的特性,在开发中会经常使用!!!!
实现了WindowFunction
,表示着其符合入参要求与其可复写apply()
方法,满足我们自己的业务逻辑编写
自定义function示例:
apply():复写此方法,编写我们自己的计算具体逻辑,参数列表意义前边已经讲过,忘了的同学向前翻一下
open(): 窗口打开时,做什么事情
open(): 窗口关闭时,做什么事情
以上,便是数量窗口的初步使用,我们一般在窗口中结合Flink 状态来进行我们的计算逻辑处理,例如上图,根据数量窗口与键控状态MapState 进行超速逻辑计算。