Flink ProcessFunction API自定义事件处理

作用:可以访问时间戳、watermark 以及注册定时事件。还可以输出特定的一些事件,例如超时事件等。Process Function 用来构建事件驱动的应用以及实现自定义的业务逻辑(使用之前的window 函数和转换算子无法实现)。例如,Flink SQL 就是使用 Process Function 实现的。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
object WindowTest {
 
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
 
    val socketStream = env.socketTextStream("hadoop102", 7777)
 
    val dataStream: DataStream[SensorReading] = socketStream.map(d => {
      val arr = d.split(",")
      SensorReading(arr(0).trim, arr(1).trim.toLong, arr(2).toDouble)
    })
      .assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[SensorReading](Time.seconds(1)) {
        override def extractTimestamp(t: SensorReading): Long = t.timestamp * 1000
      })
 
    //自定义温度报警处理
    val processStream = dataStream.keyBy(_.id).process(new TempIncreAlert)
 
    //输出自定义业务逻辑
    processStream.print("process stream")
 
    //打印原始的dataStream
    dataStream.print("data stream")
 
 
    env.execute("window test")
  }
 
}
 
case class SensorReading(id: String, timestamp: Long, temperature: Double)
 
//温度报警处理类
class TempIncreAlert extends KeyedProcessFunction[String, SensorReading, String] {
 
  //定义一个状态,保存上一条数据的温度
  lazy val savedTemper: ValueState[Double] = getRuntimeContext.getState(new ValueStateDescriptor[Double]("lastTemp", classOf[Double]))
 
  //定义一个状态,保存定时器的时间戳
  lazy val savedTimer: ValueState[Long] = getRuntimeContext.getState(new ValueStateDescriptor[Long]("currentTimer", classOf[Long]))
 
 
  override def processElement(i: SensorReading, context: KeyedProcessFunction[String, SensorReading, String]#Context, collector: Collector[String]): Unit = {
 
    //取出上一个温度值
    val preTemp = savedTemper.value()
 
    //更新温度值
    savedTemper.update(i.temperature)
 
    //取出上一个定时器的时间戳
    val preTimerTs = savedTimer.value()
 
    //如果温度在30度以上上升,则注册定时器
    if (i.temperature > preTemp && preTemp > 30 && preTimerTs == 0) {
      //注册3秒后触发的定时器
      val ts = context.timerService().currentProcessingTime()
      context.timerService().registerProcessingTimeTimer(ts + 3000)
 
      //保存刚注册的定时器时间戳
      savedTimer.update(ts)
    } else if (i.temperature < preTemp || preTemp == 0) {
      //删除定时器
      context.timerService().deleteProcessingTimeTimer(preTimerTs)
      //清空状态
      savedTimer.clear()
    }
 
  }
 
  //定时器回调函数
  override def onTimer(timestamp: Long,
                       ctx: KeyedProcessFunction[String, SensorReading, String]#OnTimerContext,
                       out: Collector[String]): Unit = {
    //输出报警信息
    out.collect(ctx.getCurrentKey + "温度超过30度且连续上升!")
  }
}

端口输入数据

[atguigu@hadoop102 ~]$ nc -lk 7777
sensor_1, 1547718200, 30
sensor_1, 1547718200, 29    
sensor_1, 1547718200, 31
sensor_1, 1547718200, 33

控制台打印

data stream> SensorReading(sensor_1,1547718200,30.0)
data stream> SensorReading(sensor_1,1547718200,29.0)
data stream> SensorReading(sensor_1,1547718200,31.0)
data stream> SensorReading(sensor_1,1547718200,33.0)
process stream> sensor_1温度超过30度且连续上升!

 

 

  

 

posted @   地中有山  阅读(579)  评论(0编辑  收藏  举报
编辑推荐:
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
阅读排行:
· 手把手教你更优雅的享受 DeepSeek
· 腾讯元宝接入 DeepSeek R1 模型,支持深度思考 + 联网搜索,好用不卡机!
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库
点击右上角即可分享
微信分享提示