Flink 自定义Trigger实现带超时时间的计数窗口

// 时间推进是必然发生的, 而数量是可能积攒不够的, 所以用数量约束时间窗口
stream.timeWindowAll(Time.seconds(10L))
      .trigger(CountTimeoutTrigger(100L,TimeCharacteristic.ProcessingTime))
import org.apache.flink.api.common.functions.ReduceFunction
import org.apache.flink.api.common.state.ReducingStateDescriptor
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.windowing.triggers.{Trigger, TriggerResult}
import org.apache.flink.streaming.api.windowing.windows.TimeWindow


case class CountTimeoutTrigger[W <: TimeWindow](maxSize: Long, timeType: TimeCharacteristic) extends Trigger[AnyRef, W] {

  val timeDescriptor = new ReducingStateDescriptor("max-size", new Sum(), classOf[Long])

  override def onEventTime(time: Long, window: W, ctx: Trigger.TriggerContext): TriggerResult = {
    if (timeType == TimeCharacteristic.EventTime) {
      if (window.getEnd >= time) {
        fireAndPurge(window, ctx)
      } else {
        TriggerResult.CONTINUE
      }
    } else TriggerResult.CONTINUE
  }

  override def onProcessingTime(time: Long, window: W, ctx: Trigger.TriggerContext): TriggerResult = {
    if (timeType == TimeCharacteristic.ProcessingTime) {
      if (window.getEnd >= time) {
        fireAndPurge(window, ctx)
      } else {
        TriggerResult.CONTINUE
      }
    } else TriggerResult.CONTINUE
  }

  override def onElement(element: AnyRef, timestamp: Long, window: W, ctx: Trigger.TriggerContext): TriggerResult = {
    val timeState = ctx.getPartitionedState(timeDescriptor)
    timeState.add(1L)
    if (timeState.get() >= maxSize) {
      fireAndPurge(window, ctx)
    } else {
      TriggerResult.CONTINUE
    }
  }

  def fireAndPurge(window: W, ctx: Trigger.TriggerContext): TriggerResult = {
    clear(window, ctx)
    TriggerResult.FIRE_AND_PURGE
  }

  override def clear(window: W, ctx: Trigger.TriggerContext): Unit = {
    ctx.getPartitionedState(timeDescriptor).clear()
  }

  class Sum extends ReduceFunction[Long] {
    override def reduce(value1: Long, value2: Long): Long = value1 + value2
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值