处理函数
无论是基本的转换、聚合,还是更为复杂的窗口操作,其实都是基于 DataStream 进行转换的;所以可以统称为 DataStream API,这也是 Flink 编程的核心
在更底层,我们可以不定义任何具体的算子(比如 map,filter,或者 window),而只是提炼出一个统一的 “处理”(process)操作
它是所有转换算子的一个概括性的表达,可以自定义处理逻辑,所以这一层接口就被叫作 “处理函数”(process function)
在处理函数中,我们直面的就是数据流中最基本的元素:数据事件(event)、状态(state)以及时间(time)
可以说,处理函数是我们进行 Flink 编程的“大招”,轻易不用,一旦放出来必然会扫平一切
stream.process(new MyProcessFunction())
处理函数的分类
对于不同类型的流,其实都可以直接调用.process()方法进行自定义处理,这时传入的参数就都叫作处理函数
当然,它们尽管本质相同,都是可以访问 状态和时间信息的底层 API,可彼此之间也会有所差异
1)ProcessFunction
抽象类 ProcessFunction 继承了 AbstractRichFunction,有两个泛型类型参数:I 表示 Input,也就是输入的数据类型;O 表示 Output,也就是处理完成之后输出 的数据类型
内部单独定义了两个方法:一个是必须要实现的抽象方法.processElement();另一个是非抽象方法.onTimer()
-
.processElement()用于“处理元素”,定义了处理的核心逻辑,它有三个参数具体如下:
-
输入元素:正在处理的数据,类型与流中数据类型一致
-
当前运行的上下文:可以获取到当前的时间戳,并提供了用于查询时间和注册定时器的“定时服务”,以及将数据发送到“侧输出流”的方法
.output(),定义如下public abstract class Context { public abstract Long timestamp(); public abstract TimerService timerService(); public abstract <X> void output(OutputTag<X> outputTag, X value); } -
收集器:可以调用
.collect()收集数据,可以多次调用,也可以不调用
-
-
.onTimer()这个方法是用于定时触发的操作,只有在
.processElement()中注册好的定时器触发的时候才会调用本质上是一个基于时间的“回调”方法,通过时间的进展来触发;在事件时间语义下就是由watermark来触发
它也有三个参数:时间戳、上下文和收集器,这里的时间戳是指设定好的触发时间,事件时间语义下即watermark
处理函数都是基于事件触发的,水位线就如同插入流中的一条数据一样; 只不过处理真正的数据事件调用的是.processElement()方法,而处理水位线事件调用的是.onTimer()
需要注意的是:在 Flink 中,只有“按键分区流” KeyedStream才支持设置定时器的操作,
所以一般情况下,我们都是先做了 keyBy 分区之后,再去定义处理操作;
代码中其实更加 常见的处理函数是 KeyedProcessFunction,最基本的 ProcessFunction 反而出镜率没那么高
2)KeyedProcessFunction
我们只要基于 keyBy 之后的 KeyedStream,直接调用.process()方法,这时需要传入的参数就是 KeyedProcessFunction 的实现类
KeyedProcessFunction 的一个特色,就是可以灵活地使用定时器
注册定时器的功能,是通过上下文中提供的“定时服务”(TimerService)来实现的,具体可由上下文对象提供的.timerService()方法获取
TimerService 是 Flink 关于时间和定时器的基础服务接口,包含以下六个方法
// 获取当前的处理时间
long currentProcessingTime();
// 获取当前的水位线(事件时间)
long currentWatermark();
// 注册处理时间定时器,当处理时间超过 time 时触发
void registerProcessingTimeTimer(long time);
// 注册事件时间定时器,当水位线超过 time 时触发
void registerEventTimeTimer(long time);
// 删除触发时间为 time 的处理时间定时器
void deleteProcessingTimeTimer(long time);
// 删除触发时间为 time 的处理时间定时器
void deleteEventTimeTimer(long time);
注意:未作按键分区的 DataStream 不支持定时器操作,只能获取当前时间

浙公网安备 33010602011771号