为什么在flink会话窗口中每个键只能得到一个窗口以上

时间:2019-05-29 15:30:13

标签: scala session apache-flink

我的要求是检查会话中的开始事件和成功事件。我当然使用会话窗口,但是似乎每个键都有重叠的窗口。我在网上搜索过,不知道为什么。

数据格式:myForm(timestamp, roomId, role, sessionId, event),例如:

myform(1559128942, 123, kid, 37890, begin) # timestamp equals to 2019-05-29 19:22:22.605  
myform(1559128944, 123, kid, 37890, success) # timestamp equals to 2019-05-29 19:22:24.844  
myform(1559129977, 456, kid, 38239, begin) # timestamp equals to 2019-05-29 19:39:37  
...

会话可能只有一对开始和成功事件,也可能有几对开始和成功事件。
事件可能会迟到,并且最多可以延迟3分钟。

我的密钥是roomId + role + sessionId,例如“ 123_kid_37890”,seesionGap是60秒

// use event time
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
val stream = ... // from kafka, steam of myform
val sessionStream = stream
    .assignTimestampsAndWatermarks(new MyFormEventWatermarks(0L))
    .keyBy(mf => mf.roomId + "_" + mf.role + "_" + mf.sessionId)
 .window(EventTimeSessionWindows.withGap(Time.milliseconds(60 * 1000L))      
.allowedLateness(Time.minutes(3))
.apply(myFormWindowFunction)

//MyFormEventWatermarks is :
class MyFormEventWatermarks[T <: AbstractForm](dely: Long) extends AssignerWithPeriodicWatermarks[T] {

  private var currentMaxTimestamp = Long.MinValue
  val maxOutOfOrderness = dely

  @transient
  var waterMark : Watermark = null

  override def getCurrentWatermark: Watermark = {
    if (currentMaxTimestamp == Long.MinValue){
      waterMark = new Watermark(Long.MinValue)
      waterMark
    }
    else{
      waterMark = new Watermark(currentMaxTimestamp - maxOutOfOrderness)
      waterMark
    }
  }

  override def extractTimestamp(data: T, previousElementTimestamp: Long): Long = {
    val timestamp = data.timestamp
    currentMaxTimestamp = Math.max(timestamp, currentMaxTimestamp)
    timestamp
  }


}


//window func is 
class myFormWindowFunction extends RichWindowFunction ... {
    ...
    override def apply(key: String, window: TimeWindow, input: Iterable[myForm], out: Collector[List[myForm]]): Unit = {
        println("window is " + window.getStart() + "-" + window.getEnd() + "|" + data.tostring)

    }
    ...

}

apply的方法myFormWindowFunction中,println的结果如下:

// like this session data:
myform(1559128942, 123, kid, 37890, begin) # timestamp equals to 2019-05-29 19:22:22.605  
myform(1559128944, 123, kid, 37890, success) # timestamp equals to 2019-05-29 19:22:24.844  

我有一个2019-05-29 19:22:22.605- 2019-05-29 19:23:22.605窗口,数据是myform(1559128942, 123, kid, 37890, begin),然后又有一个2019-05-29 19:22:22.605 - 2019-05-29 19:23:24.844窗口,数据是myform(1559128942, 123, kid, 37890, begin), myform(1559128944, 123, kid, 37890, success)。 看起来窗口初始化为(2019-05-29 19:22:22.605,2019-05-29 19:23:22.605)和(2019-05-29 19:22:24.844,2019-05-29 19:23 :24.844)和onMerge方法合并但不“丢弃”窗口(2019-05-29 19:22:22.605,2019-05-29 19:23:22.605)。我查看了EventTimeSessionWindows的源函数和flink会话窗口的示例,仍然不知道程序哪里出错了?

2 个答案:

答案 0 :(得分:0)

我发现了问题,我对allowedLateness产生了误解。使用时,将保存窗口,并在窗口+ allowLateness时间到达时,将再次触发窗口。

答案 1 :(得分:0)

在允许的延迟时间间隔内分配给窗口的事件的默认行为是在将每个延迟的事件添加到窗口时触发窗口-但也可以实现自定义触发器,该触发器在允许的过期时间触发代替其他触发或除其他触发之外的最新延迟。

请注意,在会话窗口中,迟到的事件可能会导致合并晚。

您可能需要考虑在加水印延迟和允许的延迟之间进行权衡。因为您的水印延迟为零,所以您很可能会发生一些较晚的事件(每次事件流在时间戳上的排列顺序都不理想)。举例来说,如果您使用3分钟作为水印延迟,并将允许的延迟设置为零,那么您将产生相同的最终结果,但没有延迟的触发和合并的延迟-但在初始时间之前有3分钟的延迟触发每个窗口。