Flink:Window不会在流结束时处理数据

时间:2017-09-26 17:17:51

标签: apache-kafka apache-flink flink-streaming

我有一个使用flink kafka消费者的流(kafka msgs正在流入某个主题),我注意到了一个我想要解决的有趣行为。

当数据正在流入时,如果它在窗口完成之前停止,或者如果数据结束(在几个窗口之后)并且没有到达窗口的末尾,则其余管道没有触发。

示例流程:

    env.addSource(kafkaConsumer)
       .flatMap(new TokenMapper())
       .keyBy("word")
       .window(TumblingEventTimeWindows.of(Time.seconds(10L)))
       .reduce(new CountTokens())
       .flatMap(new ConvertToString())
       .addSink(producer);

我正在使用FlinkKafkaConsumer010,并将env TimeCharacteristic设置为EventTime。和consumer.assignTimestampsAndWatermarks(new PeriodicWatermarks())

private static class PeriodicWatermarks implements   AssignerWithPeriodicWatermarks<String>{

    private long currentMaxTimestamp;
    private final long maxOutOfOrderness;

    public PeriodicWatermarksAuto(long maxOutOfOrderness){
        this.maxOutOfOrderness = maxOutOfOrderness;
    }

    @Override
    public Watermark getCurrentWatermark() {
         return new Watermark(currentMaxTimestamp - maxOutOfOrderness);
    }

    @Override
    public long extractTimestamp(String t, long l) {
        // this should be the event timestamp
        currentMaxTimestamp = l;
        logger.info("TIMESTAMP: " + l);
        return l;
    }
}

如果我的窗口说10秒,而我的数据流只包含8秒的数据(然后停止流式播放一段时间),则flatMap-&gt;接收器在新的后续数据流入之前不会处理。

示例数据流处理问题:(每个x是每秒一段数据 )

      xxxxxxxx(8secs)------(gap)--(later more data)xxxxx
      ^(not processed)           (until I get here)^

同样地,例如,如果我有35秒的流数据(并且我的窗口再次是10秒),则仅触发3个窗口的数据,并且剩余的5秒数据永远不会处理。

     ...xxxxxxxxxx(10secs)xxxxx(5secods)------(gap)--(later more data)xxxxx
         (processed)        ^(not processed)          (until I get here)^

最后如果我的窗口是10秒而我有5秒的流数据,则flatmap-&gt;接收器永远不会发生。

我的问题是,如果我们在一段时间后看不到数据,有没有办法触发窗口数据处理?

如果我的数据是实时流式传输的,我可以看到存在无数据的延伸,并且不希望最后一个窗口(假设只有5秒的数据)必须等待一段不确定的时间,直到新数据进来后,我想要在窗口时间过后最后一个窗口的结果。

大声思考,这似乎是由于使用EventTime而不是ProcessingTime,或者,我的水印没有正确生成最后一个窗口实际触发...不确定可能两者兼而有之?我认为这对任何人都是一个问题,如果你的流结束最后一点不会触发。我会说我可能会发送一个流末尾的消息,但如果蒸汽结束因为消息来源中断,这无济于事。

编辑:所以我改为处理时间,它确实正确处理了最后一个窗口中的数据,所以我猜EventTime是后来的罪魁祸首,我认为自定义触发器或正确的窗口水印可能就是答案。 ..

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

我将这个问题留给子孙后代,因为问题与我想的一样,与水印有关。时间戳和watermaker(来自assignTimestampsAndWatermarks)调用&#39; getCurrentWatermark()&#39;因为我将基于传入实体的水印设置为固定数字(它们的时间戳 - 最大偏移量),所以在它看到新的权利之前不会更新。

我的解决方案是某种计时器,如果在可配置的时间内没有看到数据,最终会将水印推进到下一个窗口。我将无法处理非常潜在的数据,但我不认为这应该是一个问题。这是EventTime处理的预期行为。