之前提到的一些算子和函数能够进行一些时间上的操作,但是不能获取算子当前的Processing Time或者是Watermark时间戳,调用起来简单但功能相对受限。如果想获取数据流中Watermark的时间戳,或者在时间上前后穿梭,需要使用ProcessFunction
系列函数,它们是Flink体系中最底层的API,提供了对数据流更细粒度的操作权限。Flink SQL是基于这些函数实现的,一些需要高度个性化的业务场景也需要使用这些函数。
目前,这个系列函数主要包括KeyedProcessFunction
、ProcessFunction
、CoProcessFunction
、KeyedCoProcessFunction
、ProcessJoinFunction
和ProcessWindowFunction
等多种函数,这些函数各有侧重,但核心功能比较相似,主要包括两点:
-
状态:我们可以在这些函数中访问和更新Keyed State 。
-
定时器(Timer):像定闹钟一样设置定时器,我们可以在时间维度上设计更复杂的业务逻辑。
状态的介绍可以参考我的文章:Flink状态管理详解,这里我们重点讲解一下的使用ProcessFunction
其他几个特色功能。本文所有代码都上传到了我的github:https://github.com/luweizheng/flink-tutorials
Timer的使用方法
我们可以把Timer理解成一个闹钟,使用前先在Timer中注册一个未来的时间,当这个时间到达,闹钟会“响起”,程序会执行一个回调函数,回调函数中执行一定的业务逻辑。这里以KeyedProcessFunction
为例,来介绍Timer的注册和使用。
ProcessFunction
有两个重要的接口processElement
和onTimer
,其中processElement
函数在源码中的Java签名如下:
// 处理数据流中的一条元素
public abstract void processElement(I value, Context ctx, Collector<O> out)
processElement
方法处理数据流中的一条元素,并通过Collector<O>
输出出来。Context
是它的区别于FlatMapFunction
等普通函数的特色,开发者可以通过Context
来获取时间戳,访问TimerService
,设置Timer。