Apache flink 使用广播状态使用假消息强制关闭窗口

Apache flink 使用广播状态使用假消息强制关闭窗口,apache-flink,flink-streaming,Apache Flink,Flink Streaming,说明: 目前我正在使用Flink进行物联网设置。本质上,设备正在发送数据,例如(设备id、设备类型、事件时间戳等),我无法控制消息何时发送。然后,我按设备id和设备类型为steam设置键,以预成型聚合。我想使用给定的事件时间来确保在给定故障的情况下,设置为确定性触发的计时器。然而,考虑到这并不总是一个高吞吐量的流,可以在10分钟的聚合周期内打开一个窗口,但直到大约40分钟后,它的下一个点才会出现。虽然计算最终会完成,但它会非常晚地输出我想要的结果 因此,我的工作是创建一个额外的外部源,它除了发送

说明:

目前我正在使用Flink进行物联网设置。本质上,设备正在发送数据,例如(设备id、设备类型、事件时间戳等),我无法控制消息何时发送。然后,我按设备id和设备类型为steam设置键,以预成型聚合。我想使用给定的事件时间来确保在给定故障的情况下,设置为确定性触发的计时器。然而,考虑到这并不总是一个高吞吐量的流,可以在10分钟的聚合周期内打开一个窗口,但直到大约40分钟后,它的下一个点才会出现。虽然计算最终会完成,但它会非常晚地输出我想要的结果

因此,我的工作是创建一个额外的外部源,它除了发送虚假消息之外什么也不做。通过让这些假消息与我的10分钟聚合周期相一致,即使设备没有发送任何数据,事件时间窗口也会有一些东西迫使窗口关闭。这里的关键部分是使所有并行实例/操作员都能够访问此假消息,因为我需要使用此假消息关闭所有窗口。我认为广播状态可能是实现这一目标的最合适的方式,因为:“广播状态在一个函数的所有并行实例中都是复制的,通常可以在有两个流的情况下使用,一个常规数据流和一个控制流,该控制流提供规则、模式或其他配置消息。”

问题:

  • 广播状态是否是确保所有并行实例(如windows)接收我的假消息的最佳方法
  • 一旦运营商通过广播状态访问该假消息,该假消息是否可用于提前事件时间水印

  • 您可以按照您提出的思路,在广播状态下实现这一点,但我不认为这是最好的解决方案

    在理想情况下,我建议您安排设备偶尔发送keepalive消息,但假设这不可能,我认为定制触发器在这里会很好地工作。您可以扩展EventTimeTrigger,以便除了通过

    ctx.registerEventTimeTimer(window.maxTimestamp());
    
    您还创建了一个处理时间计时器作为备用,如果在该处理时间计时器启动时窗口仍然存在,则启动该窗口


    我推荐这种方法,因为它更简单,更直接地满足特定的需求。使用广播状态方法,您必须为这些消息引入源,添加广播状态描述符和流,为非广播流添加特殊的伪水印(设置为水印.MAX_水印),连接广播流和非广播流,并实现BroadcastProcessFunction(这可能没什么用)等等。这是许多移动部件分散在几个不同的运营商之间。

    你是说任何设备可能在大约40分钟内没有任何事件?我问,因为任何事件都可以推进水印并关闭窗口——它不一定是特定设备的事件。嘿@DavidAnderson,是的,这正是我所说的。有可能让设备全天启动,然后在一天结束时所有设备都停止发送事件。事后看来,我意识到这是一个更好的例子来解释。因此,现在一天结束了,窗口没有关闭,直到第二天设备再次开始发送事件,我才看到聚合。所以我尝试确定是否有方法强制关闭此窗口。基本上,我希望有一种方法可以说,嘿,没有事件发生,所以现在是我发送水印的时候了。感谢David的建议,我将更多地研究创建自定义触发器。是否可以详细说明为什么您不认为广播不是一个好的解决方案?我感谢您的建议更新,我认为它清楚地显示了这种方法的缺点。以前,我唯一列出的缺点是现在我的Flink应用程序依赖于外部的东西来发送我的心跳,这一点都不好。我没有想到需要在我的非广播流上创建特殊的假水印。广播流的来源是你不必是外部的。你可以很容易地实现一个自定义源,它使用定时器来发出水印。或者你可以实现一个特殊的水印生成器,它关注实时的传递,并在没有事件的情况下推进水印。请看一个例子。但是在所有这些解决方案中,我很确定自定义源不会索具将是最容易和最易维护的。