Ack 框架分析

Ack介绍

 每个Spout Tuple保存一个ack-val的校验值,它的初始值是0,然后每发射一个Tuple或者ack一个Tuple,Tuple的ID都要跟这个校验值异或一下,并把得到的值更新为ack-val的新值。

如果每个发射出去的Tuple都被ack了,最后ack-val一定是0(因为一个数字跟自己异或得到的值是0)。如果ack-val为0,表示这个Tuple树就被完整处理过了。当达到超时时间,ack-val不为0,则Tuple处理失败了。


Ack框架执行过程

1) Storm的Spout中对每条发射出去的消息生产一个MessageId 对象,内容为<RootId,消息ID>,消息ID为一个64位的随机数,并且Spout会以RootId为键,以消息为值,放到自己的pendingMap中,并且只保留一段时间,具体时间有Topology.message.timeout.secs决定,超时后则调用Spout的fail方法。

2)Spout发送消息出去之后,给Acker Bolt 发射一条Tuple消息,消息的内容为[ tuple-id , ack-val, task-id]。

    a) tuple-id 为消息的RootId

    b) Spout发送的消息有一个或者多个接受目标Task,对所有的目标Task的消息ID进行异或,得到ack-val。

    c) task-id 为spout的ID,这样Acker就知道是哪个Spout发送过来的Ack信息了。

    d)发送消息的StreamId是_ack_init(ACKER-INIT-STREAM-ID)。

3)Acker Bolt收到StreamId为ACKER-INIT-STREAM-ID的消息后,会在自己的pending对象中添加一个记录{tuple-id :  { task-id : ack-val  } },记录中的各项值从Spout中发送过来。

4)Bolt收到的消息中(来源于Spout或者父Bolt) 同样会包含MessageId对象。Bolt在发射信息的过程中,对每个需要接受该信息的Task,会创建一个新的MessageId对象。该MessageId对象会发送给目标Task,并且该MessageId的消息Id和接受到的消息Id进行异或,把得到的ack-val发送给Acker Bolt。发送给Acker的消息内容为<tuple-id, ack-val>,消息的StreamId为_ack_ack(ACKER_ACK_STREAM_ID).

5)Acker Bolt收到StreamId 为ACKER_ACK_STREAM_ID的消息后,根据tuple-id从pending中取出老的ack-val,并将新的ack-val进行异或操作,跟新到新的pending中。

6)如果第5步的异或结果为0,则Acker Bolt 认为从Spout发出的消息已经正确处理完毕了。就会给spout发送通知。消息的内容为tuple-id,StreamId 为_ack_ack(ACKER_ACK_STREAM_ID)).

7)Spout收到StreamId后,则将pendingMap中的tuple-id记录删除,并调用Spout的ack方法。

8)如果第1步中spout发射消息的时候,不指定消息ID,则Storm不会启动ACK跟踪。如果系统中不含Acker Bolt,也不会启用Ack。

9)如果Bolt调用fail方法,会给Acker Bolt发送StreamId为_ack_fail(ACKER_FAIL_STREAM_ID)的消息。Acker Bolt收到ACKER_FAIL_STREAM_ID的消息,会将该消息转发给对应的spout。spout收到fail消息后,则执行spout的fail方法。

10)Acker Bolt的pending中,只会保存一段时间的跟踪信息,具体时间根据topology.message.timeout.secs决定的,超过这个时间,就会删除这个tuple-id的跟踪信息。如果后续收到Bolt发送的跟踪信息,则会出发Acker发送ACKER_FAIL_STREAM_ID的消息。


举例说明,Ack框架执行过程


 

1) spout产生一个Tuple,其初始化的消息ID为0100,Spout同时将该消息ID发送给Acker和Bolt1.

2)Bolt1收到Spout发送过来的消息ID为0100消息,经过处理之后,产生新的消息,消息ID为0010,Bolt1就讲 0100 xor 0010的结果发送给Acker。

3)Bolt2接收到Bolt1的消息,处理完后,没有后续的消息产生,则直接将Bolt1的消息ID转发给Acker。

4)Acker中,此时ack-val值已经为0,因此StreamId为ACKER_ACK_STREAM_ID的流上发送相应的消息。Spout收到消息后,调用spout的ack方法,完成整个消息流的ack操作,确认所有的消息都被正确处理了。







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值