apache beam 入门之触发器

目录:apache beam 个人使用经验总结目录和入门指导(Java)

概念

触发器指 窗口的触发策略, 即窗口何时可以把该窗口内收集到的数据向下发送。
而手动设定触发器可以让我们做到2件事:

  1. 在窗口时间内, 我可以实现多次触发而不是像默认那样仅仅在窗口结束时触发1次
  2. 我可以对延迟数据做特殊触发,而不是像默认那样,1收到延迟数据就触发。

触发器使用p.apply(窗口对象.triggering(触发器对象) 来进行设定

以下介绍各类触发器。

默认触发器

当 “当前时间” 超过了窗口右界,则触发1次, 同时在延迟水位线前,每收到延迟数据就会触发1次
如下图所示:
在这里插入图片描述
红色方框指代每次的触发

处理时间触发器(针对真正意义上的处理时间)

该触发器在窗口内收到第一个数据之后, 开启1个x秒的小窗口,收集这x秒内(注意这x秒是真正意义上的计算机运行时间,而不是输入时间戳上的时间)该窗口的数据,并进行触发。
我设定处理触发时间为6秒,则第一次收到1000后, 会开启1个6s的窗口,beam会启动1个定时器,收集6秒内属于0~2999的数据。
如下图所示:
在这里插入图片描述

如果beam的"当前时间"已经超过水位线, 及时定时器还没到6秒,也会立刻结束窗口并触发,入下图所示,绿色是收到1000后的6s范围, 红色是触发范围:
在这里插入图片描述

处理时间触发器使用AfterProcessingTime.pastFirstElementInPane()生成,代码如下:

        PCollection<String> pTimeStrByWindow = pTimeStr
                // 3s固定窗口
                .apply(Window.<String>into(FixedWindows.of(Duration.standardSeconds(3)))
                        // 设定5s的延迟时间
                        .withAllowedLateness(Duration.standardSeconds(5))
                        // 累加方式,把之前该窗口内的数据合并到一起再计算一次
                        .accumulatingFiredPanes()
                        // 设定触发器
                        .triggering(
                                // 处理时间触发器
                                AfterProcessingTime.pastFirstElementInPane()
                                        // 窗口内当收到第1个数据后,开启1个6s的小触发窗口
                                        // 触发后就不再接收该窗口数据。
                                        .plusDelayOf(Duration.standardSeconds(6))));

数据处理个数触发器

该触发器根据收集到的个数进行触发,在窗口内,如果收集到x个,则进行触发,后续不再做收集
。 如果未收集到x个,但是已经到达了水位线,还是会触发
假设我们设定x为3,则触发情况如下图所示,可以看到收集3个之后的不再收集:
在这里插入图片描述
代码示例如下:

        PCollection<String> pTimeStrByWindow = pTimeStr
                // 3s固定窗口
                .apply(Window.<String>into(FixedWindows.of(Duration.standardSeconds(3)))
                        // 设定5s的延迟时间
                        .withAllowedLateness(Duration.standardSeconds(5))
                        // 累加方式,把之前该窗口内的数据合并到一起再计算一次
                        .discardingFiredPanes()
                        // 设定触发器
                        .triggering(
                                // 处理个数触发器,收集到至少3个或者到达水位线末尾触发
                                // 也是只触发1次
                                AfterPane.elementCountAtLeast(3)));

水位线触发器

如果使用AfterWatermark.pastEndOfWindow()这个触发器,则会在窗口结束时立刻触发,而不会处理延迟数据,如下图所示:
在这里插入图片描述

水位线触发器之处理延迟数据

如果希望处理延迟数据, 需要再调用.withLateFirings(触发器对象) 来设定1个窗口右界->水位线之间的触发器。
假设我们希望在 窗口->水位线之间, 收到延迟数据的话,则启动1个5s的处理时间触发器,则代码可以如下:

        PCollection<String> pTimeStrByWindow = pTimeStr
                // 3s固定窗口
                .apply(Window.<String>into(FixedWindows.of(Duration.standardSeconds(3)))
                        // 设定5s的延迟时间
                        .withAllowedLateness(Duration.standardSeconds(5))
                        // 累加方式,把之前该窗口内的数据合并到一起再计算一次
                        .discardingFiredPanes()
                        // 设定触发器
                        .triggering(
                                // 窗口结束马上触发
                                AfterWatermark.pastEndOfWindow()
                                        // 窗口结束到水位线之间,启用处理时间触发器
                                        // 如果收到1个延迟数据,就开启3s小窗口收集该窗口范围的数据
                                        // 并且是持续的,如果未过水位线
                                        // 只要收到1个延迟数据且小窗口已结束,就可以再次开始这个3s小窗口做触发
                                        .withLateFirings(
                                                AfterProcessingTime.pastFirstElementInPane()
                                                        .plusDelayOf(Duration.standardSeconds(5)))
                        ));

与前文提到的不同, 在窗口触发器中用withLateFiring去设定延迟触发器时, 这个触发器在窗口内是持续性的而非一次性的,如下图所示,绿色是延迟触发器触发的延迟窗口数据:

在这里插入图片描述
同理,我们也可以用withLateFirings来设定1个数据处理个数的延迟触发器,这个就不再举例。

水位线触发器之在窗口结束前提前处理数据

水位线触发器会在窗口结束(即00:00:03)时触发1次, 但是我如果希望在窗口结束前,也做一些特殊的触发, 即希望在结束前,每2个元素触发1次, 则可以写如下代码:

        PCollection<String> pTimeStrByWindow = pTimeStr
                // 3s固定窗口
                .apply(Window.<String>into(FixedWindows.of(Duration.standardSeconds(3)))
                        // 设定5s的延迟时间
                        .withAllowedLateness(Duration.standardSeconds(5))
                        // 累加方式,把之前该窗口内的数据合并到一起再计算一次
                        .discardingFiredPanes()
                        // 设定触发器
                        .triggering(
                                // 窗口结束马上触发
                                AfterWatermark.pastEndOfWindow()
                                        // 窗口结束前,每2个元素收集1个小窗口并触发
                                        // 并且是持续性而非一次性的
                                .withEarlyFirings(AfterPane.elementCountAtLeast(2))
                        ));

触发情况如下:
在这里插入图片描述
该窗口在累积模式下会触发3次, 输出[1000,2000] [1000,2000,1000,2000] 和[1000,2000,1000,2000]

水位线触发器可以将withEarlyFirings和withLateFirings二者一起使用,从而实现窗口内的连续性触发,以及延迟数据的连续触发。

复合触发器

可以组合多个触发器来形成复合触发器,并且可以指定触发器的触发方式:重复发出结果,最多一次或其他自定义条件。

复合触发器的类型

Beam包括以下复合触发器:

  • 可以通过.withEarlyFirings和.withLateFirings向AfterWatermark.pastEndOfWindow添加额外的提前触发或延迟启动。

  • Repeatedly.forever指定一个永远重复执行的触发器。任何触发条件满足时,都会导致窗口发出结果,然后重置并重新开始。将Repeatedly.forever与.orFinally组合可以指定重复触发器停止的条件。

  • AfterEach.inOrder组合多个触发器以特定的顺序启动。每次序列中的触发器发出一个窗口,然后指向下一个触发器。

  • AfterFirst需要多个触发器,并且首次发出任何一个参数触发器都被满足。相当于多个触发器的逻辑OR运算。

  • AfterAll需要多个触发器,并在其所有参数触发器都满足时发出。相当于多个触发器的逻辑AND运算。

  • orFinally 可以作为最后的条件,引起任何触发器最后一次启动,再也不能再次触发。

例如,希望每当窗格至少有100个元素或每1分钟触发1次。 则触发器可以设定如下:

Repeatedly.forever(AfterFirst.of(
      AfterPane.elementCountAtLeast(100),
      AfterProcessingTime.pastFirstElementInPane().plusDelayOf(Duration.standardMinutes(1))))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值