Flink传感器温度监控预警

需求:监控温度传感器的温度值,如果温度值在10秒钟之内(processing time)连续上升,则报警。

package com.run.wc

import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.scala.{DataStream, StreamExecutionEnvironment}
import org.apache.flink.api.scala._
import org.apache.flink.streaming.api.functions.KeyedProcessFunction
import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.util.Collector

/**
 * @author 霄嵩
 */
object ProcessFunctionTest {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    env.setParallelism(1)
    //接收数据
    val dataStream = env.socketTextStream("master", 9999)
    //分隔接收的数据,并返回一个Sensor实例对象
    val mapStream: DataStream[Sensor] = dataStream.map(x => {
      val line = x.split(",")
      new Sensor(line(0).trim.toString, line(1).trim.toLong, line(2).trim.toDouble)
    })
    //分配时间戳和水位线
    val stream = mapStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor[Sensor](Time.seconds(1)) {
      override def extractTimestamp(element: Sensor): Long = {
        element.timestamp * 1000
      }
    })
    //先对id进行分区,然后通过ProcessFunction(底层API)进行操作
    val processStream = stream.keyBy(_.id)
      .process(new TempIncrese())

    //输出
    mapStream.print("sensor data:")
    processStream.print("process function:")

    //执行操作
    env.execute("process function test")
  }
}

class TempIncrese extends KeyedProcessFunction[String, Sensor, String] {

  //定义一个状态,用于保存上一个数据的温度值
  lazy val lastTemp: ValueState[Double] = this.getRuntimeContext
    .getState(new ValueStateDescriptor[Double]("lastTemp", classOf[Double]))
  //定义一个状态,保存定时器的时间戳
  lazy val currentTimer: ValueState[Long] = getRuntimeContext
    .getState(new ValueStateDescriptor[Long]("currentTimer", classOf[Long]))

  //流中的每一个元素都会调用这个方法,调用结果将会放在 Collector 数据类型中输出
  override def processElement(value: Sensor,
                              ctx: KeyedProcessFunction[String, Sensor, String]#Context,
                              out: Collector[String]): Unit = {
    //取出上一个温度值
    val preTemp = lastTemp.value()
    //取出保存的定时器的时间戳
    val curTimer = currentTimer.value()
    //更新温度值
    lastTemp.update(value.temperature)

    //如果当前元素的温度值大于上一次的温度值,并且没有设置定时器,那么就设置定时器
    if (value.temperature > preTemp && curTimer == 0.0) {
      //获取当前事件时间,并加上10s,即10000ms
      val timeTs = ctx.timerService().currentProcessingTime() + 10000
      //注册事件时间定时器,10秒钟之后触发
      ctx.timerService().registerProcessingTimeTimer(timeTs)
      //更新定时器时间戳
      currentTimer.update(timeTs)
    } else if (value.temperature < preTemp || preTemp == 0.0) {
      //如果当前元素的温度值小于上一次的温度值,或者当前是第一个温度值,就删除定时器
      ctx.timerService().deleteProcessingTimeTimer(curTimer)
      //清空状态变量
      currentTimer.clear()
    }
  }

  /**
   * onTimer(timestamp: Long, ctx: OnTimerContext, out: Collector[OUT])是一个回调函数。当之前注册的定时器触发时调用。
   *
   * @param timestamp 定时器所设定的触发的时间戳
   * @param ctx
   * @param out       输出结果的集合
   */
  override def onTimer(timestamp: Long,
                       ctx: KeyedProcessFunction[String, Sensor, String]#OnTimerContext,
                       out: Collector[String]): Unit = {
    out.collect("传感器id为:" + ctx.getCurrentKey + "传感器的温度值已连续上升。")
  }
}

Result:
sensor data:> Sensor(sensor_1,1547718207,35.6)
sensor data:> Sensor(sensor_1,1547718207,36.0)
process function:> 传感器id为:sensor_1传感器的温度值已连续上升。
sensor data:> Sensor(sensor_1,1547718207,37.0)
sensor data:> Sensor(sensor_1,1547718207,35.0)
sensor data:> Sensor(sensor_1,1547718207,35.6)
sensor data:> Sensor(sensor_1,1547718207,34.0)
sensor data:> Sensor(sensor_1,1547718207,35.6)
sensor data:> Sensor(sensor_1,1547718207,36.0)
process function:> 传感器id为:sensor_1传感器的温度值已连续上升。
sensor data:> Sensor(sensor_1,1547718207,37.0)

你可能感兴趣的:(Flink)