ProcessFunction 是一个低层次的流处理操作,允许返回所有 Stream 的基础构建模块:
- 访问 Event 本身数据(比如:Event 的时间,Event 的当前 Key 等)
- 管理状态 State(仅在 Keyed Stream 中)
- 管理定时器 Timer(包括:注册定时器,删除定时器等)
- 总而言之,ProcessFunction 是 Flink 最底层的 API,也是功能最强大的。
案例:
-
问题
监控每一个手机,如果在 5 秒内呼叫它的通话都是失败的,发出警告信息。 -
代码
package com.hjf.function import com.hjf.dataSource.StationLog import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor} import org.apache.flink.streaming.api.functions.KeyedProcessFunction import org.apache.flink.streaming.api.scala.StreamExecutionEnvironment import org.apache.flink.util.Collector /** * @author Jiang锋时刻 * @create 2020-07-11 16:52 */ object TestProcessFunctionAPI { def main(args: Array[String]): Unit = { val streamEnv: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment streamEnv.setParallelism(1) import org.apache.flink.streaming.api.scala._ val stream: DataStream[String] = streamEnv.socketTextStream("node01", 8888) stream.map(one => { val arr: Array[String] = one.split(",") new StationLog(arr(0).trim, arr(1).trim, arr(2).trim, arr(3).trim, arr(4).trim.toLong, arr(5).trim.toLong) }).keyBy(_.callOut).process(new MonitorCallFail).print() streamEnv.execute() } // 控制逻辑 class MonitorCallFail() extends KeyedProcessFunction[String, StationLog, String] { // 使用一个状态记录时间 lazy val timeState: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptor[Long]("time", classOf[Long])) override def processElement(value: StationLog, context: KeyedProcessFunction[String, StationLog, String]#Context, collector: Collector[String]): Unit = { // 从状态中获取时间 var time: Long = timeState.value() // 表示第一次发现呼叫的手机号是失败的 if(value.callType.equals("fail") && time == 0) { // 获取当前时间 val nowTime: Long = context.timerService().currentProcessingTime() // 5s后触发 val onTime: Long = nowTime + 5000L // 注册定时器 context.timerService().registerProcessingTimeTimer(onTime) } // 呼叫成功, 取消定时器 if(!value.callType.equals("fail") && time != 0) { context.timerService().deleteProcessingTimeTimer(time) timeState.clear() } } // 定时器时间到了, 执行定时器, 发出警告 override def onTimer(timestamp: Long, ctx: KeyedProcessFunction[String, StationLog, String]#OnTimerContext, out: Collector[String]): Unit = { val warnStr: String = "触发时间: " + timestamp + ", 手机号" + ctx.getCurrentKey out.collect(warnStr) timeState.clear() } } }
-
运行结果: