背景
本篇看看storm是通过什么机制来保证消息至少处理一次的语义的。
storm中的一些原语
要说明上面的问题,得先了解storm中的一些原语,比如:
tuple和message
在storm中,消息是通过tuple来抽象表示的,每个tuple知道它从哪里来,应往哪里去,包含了其在tuple-tree(如果是anchored的话)或者DAG中的位置,等等信息。spout
spout充当了tuple的发送源,spout通过和其它消息源,比如kafka交互,将消息封装为tuple,发送到流的下游。- bolt
bolt是tuple的实际处理单元,通过从spout或者另一个bolt接收tuple,进行业务处理,将自己加入tuple-tree(通过在emit方法中设置anchors)或DAG,然后继续将tuple发送到流的下游。 - acker
acker是一种特殊的bolt,其接收来自spout和bolt的消息,主要功能是追踪tuple的处理情况,如果处理完成,会向tuple的源头spout发送确认消息,否则,会发送失败消息,spout收到失败的消息,根据配置和自定义的情况会进行消息的丢弃、重放处理。
spout、bolt、acker的关系
- spout将tuple发送给流的下游的bolts.
- bolt收到tuple,处理后发送给下游的bolts.
- spout向acker发送请求ack的消息.
- bolt向acker发送请求ack的消息.
- acker向bolt和spout发送确认ack的消息.
简单的关系如下所示:
上图展示了spout、bolts等形成了一个DAG,如何追踪这个DAG的执行过程,就是storm保证仅处理一次消息的语义的机制所在。
storm如何追踪消息(tuple)的处理
spout在调用emit/emitDirect方法发送tuple时,会以单播或者广播的方式,将消息发送给流的下游的component/task/bolt,如果配置了acker,那么会在每次emit调用之后,向acker发送请求ack的消息:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; spout向acker发送请求ack消息
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; rooted?表示是否设置了acker
(if (and rooted?
(not (.isEmpty out-ids)))
(do
(