ProcessFunction API (底层API)
普通的转换算子只能获取到当前的数据,或者加上聚合状态 如果RichFunction可以有生命周期方法,还可以获取运行时上下文,进行状态编程,但是都无法访问事件时间的时间戳信息和水位线相关的信息。
于是 dataStream API 提供了一系列的Low-Level转换算子。可以访问时间戳、watermark以及注册定时事件。还可以输出特定的一些事件,如超时事件。 Process Function 用来构建事件驱动的应用以及实现自定义业务逻辑 如:Flink SQL就是用Process Function实现的。
ProcessFunction 是唯一可以获取到时间相关信息的Api
Flink 提供了8个Process Function:
ProcessFunction
KeyedProcessFunction
CoProcessFunction
ProcessJoinFunction
BroadcastProcessFunction
KeyesBroadcastProcessFunction
ProcessWindowFunction
ProcessAllWindowFunction
KeyedProcessFunction 用来操作KeyedStream 。KeyedProcessFunction会处理流的每一个元素,输出为0个、1个或者多个元素。所有的ProcessFunction都继承自RichFunction接口 所以除了RichFunction 自带的 以外KeyedProcessFunction 额外有两个方法
def main(args: Array[String]): Unit = {
val env = StreamExecutionEnvironment.getExecutionEnvironment
val inputDataStream: DataStream[String] = env.socketTextStream("127.0.0.1", 9436)
val dataStream = inputDataStream.map(data => {
val dataArray = data.split(",")
SensorReading(dataArray(0), dataArray(1).toLong, dataArray(2).toDouble)
})
// 检测每一个demo 温度是否连续上升,在10秒之内
//解决方法 每条数据都为他注册一个定时器 如果10秒之后 数据是连续上升的 就触发定时器 通过KeyedProcessFunction方法
val warningStream = dataStream
.keyBy("id")
.process(new TempIncreWarining(10000L))
warningStream.print()
env.execute(" window test")
}
//自定义KeyedProcessFunction 传入 k i o k代表 key的类型 i 时输入类型 o 时输出类型
class TemIncreWarining(interval :Long) extends KeyedProcessFunction[Tuple,inputDemo,String]{
//由于需要跟之前的温度值做对比,所以将上一个温度保存成状态
lazy val lastTempState:ValueState[Double] = getRuntimeContext.getState(new ValueStateDescriptor[Double]("lastTemp",classOf[Double]))
//为了方便删除定时器,还需要保存定时器的时间戳
lazy val curTimerTsState: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptor[Double]("cur_timestamp",classOf[Double]))
//processElement 流中的每一个元素都会调用这个方法 ,调用结果会在Collector数据类型中输出
override def
processElement(value:inputDemo,ctx:KeyedProcessFunction[Tuple,inputDemo,String]#Context,out:Collector[String]):Unit = {
//timerService可以注册定时器(两种时间语义 都可以) 获取当前时间语义 获取当前watermark
//首先取出状态
val lastTemp = lastTempState.value()
val curTimerTs = curTimerTsState.value()
//将上次温度值的状态更新为当前数据的温度值
lastTempState.update(value.temperature)
//判断当前温度值,如果比之前温度高,并且没有定时器的话,注册10秒后的定时器
if(value.temperature > lastTemp && curTimerTs==0){
val ts = cdx.timerService.currentProcessingTime()+interval//定时定时器的时间戳
ctx.timerService().registerProcessingTimeTimer(ts)//注册定时器
curTimerTsState.update(ts)
}
//如果温度下降,删除定时器
else if(value.temperature < lastTemp){
ctx.timerService().deleteProcessingTimeTimer(curTimerTs)
//清空状态
curTimerTsState.clear()
}
}
//onTimer 是一个回调函数,当之前注册的定时器触发时调用
override def onTimer(timestamp:Long,ctx:KeyedProcessFunction[Tuple,inputDemo,String]#OnTimerContext,out:Collector[String]):Unit ={
out.collect(“温度值连续”+interval/1000 +“秒上升”)
curTimerTsState.clear()
}
}
Process Function 是一类特殊的函数类,是.process()方法的参数,DataStream/KeyedStream/ConnectedStream/WindowedStream .....等都可以调用.process()方法
传入的是不同的process function
如果注册了watermark。定时器的触发需要watermark的更新来触发
1179

被折叠的 条评论
为什么被折叠?



