backtype.storm.daemon.acker
设计的巧妙在于, 不用分别记录和track, stream过程中所有的tuple, 而只需要track root tuple, 而所有中间过程都通过异或更新track entry

acker-init, 在spout发送一个tuple时触发, 初始化这个root tuple的track entry 
acker-ack, 在blot ack一个tuple的时候触发, 会对该tuple的anchors-to-ids中记录的每个(root, edge)进行ack, 并出于优化还会附带登记新的edge(对acker透明, 在发送前已经完成)
acker-fail, 任一个过程中的tuple fail, 都会导致这个root tuple失败

 

(defn mk-acker-bolt []
(let [output-collector (MutableObject.)
pending (MutableObject.)]
(reify IBolt
(^void prepare [this ^Map storm-conf ^TopologyContext context ^OutputCollector collector]
(.setObject output-collector collector)
(.setObject pending (RotatingMap. 2)) ;;用RotatingMap来缓存每个tuple的track信息
)
(^void execute [this ^Tuple tuple]
(let [^RotatingMap pending (.getObject pending)
stream-id (.getSourceStreamId tuple)] ;;从ack tuple中取出streamid
(if (= stream-id Constants/SYSTEM_TICK_STREAM_ID) ;;收到system_tick_stream, rotate pending, spout的pending和acker的pending超期时间是一样的, 都取决于system-tick
(.rotate pending)
(let [id (.getValue tuple 0) ;;else,其他的stream,取出tuple id
^OutputCollector output-collector (.getObject output-collector)
curr (.get pending id) ;;取出相应tuple的track entry
curr (condp = stream-id
ACKER-INIT-STREAM-ID (-> curr ;;初始化tuple的track entry
(update-ack (.getValue tuple 1)) ;;更新entry中的track value
(assoc :spout-task (.getValue tuple 2))) ;;记录该tuple和spout-task的关系, 这样在ack或fail的时候才知道通知谁
                                ACKER-ACK-STREAM-ID (update-ack curr (.getValue tuple 1));;ack, 用val和原来的entry value做异或
                                ACKER-FAIL-STREAM-ID (assoc curr :failed true))] ;;fail, 直接把entry的:failed设true
(.put pending id curr)
(when (and curr (:spout-task curr))
(cond (= 0 (:val curr)) ;;val为0, 表示该tuple的所有edge都被成功ack
(do
(.remove pending id) ;;从pending中删除track entry, 并向相应的spout-task发送ack消息
                             (acker-emit-direct output-collector
(:spout-task curr)
ACKER-ACK-STREAM-ID
[id]
))
(:failed curr) ;;:failed为true, 表示该tuple失败
                           (do
(.remove pending id) ;;从pending中删除track entry, 并向相应的spout-task发送fail消息
                             (acker-emit-direct output-collector
(:spout-task curr)
ACKER-FAIL-STREAM-ID
[id]
))
))
(.ack output-collector tuple) ;;acker bolt也是bolt, 所以最后完成对该ack tuple的ack
))))
(^void cleanup [this]
)
)))

 

(defn- update-ack [curr-entry val]
(let [old (get curr-entry :val 0)] ;;取出entry中的value值,默认设为0
(assoc curr-entry :val (bit-xor old val)) ;;将old和新val异或, 赋给entry的value
))

Storm-源码分析-acker (backtype.storm.daemon.acker)的更多相关文章

  1. Storm源码分析--Nimbus-data

    nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...

  2. JStorm与Storm源码分析(四)--均衡调度器,EvenScheduler

    EvenScheduler同DefaultScheduler一样,同样实现了IScheduler接口, 由下面代码可以看出: (ns backtype.storm.scheduler.EvenSche ...

  3. JStorm与Storm源码分析(三)--Scheduler,调度器

    Scheduler作为Storm的调度器,负责为Topology分配可用资源. Storm提供了IScheduler接口,用户可以通过实现该接口来自定义Scheduler. 其定义如下: public ...

  4. JStorm与Storm源码分析(二)--任务分配,assignment

    mk-assignments主要功能就是产生Executor与节点+端口的对应关系,将Executor分配到某个节点的某个端口上,以及进行相应的调度处理.代码注释如下: ;;参数nimbus为nimb ...

  5. JStorm与Storm源码分析(一)--nimbus-data

    Nimbus里定义了一些共享数据结构,比如nimbus-data. nimbus-data结构里定义了很多公用的数据,请看下面代码: (defn nimbus-data [conf inimbus] ...

  6. storm源码分析之任务分配--task assignment

    在"storm源码分析之topology提交过程"一文最后,submitTopologyWithOpts函数调用了mk-assignments函数.该函数的主要功能就是进行topo ...

  7. storm源码分析之topology提交过程

    storm集群上运行的是一个个topology,一个topology是spouts和bolts组成的图.当我们开发完topology程序后将其打成jar包,然后在shell中执行storm jar x ...

  8. Nimbus<三>Storm源码分析--Nimbus启动过程

    Nimbus server, 首先从启动命令开始, 同样是使用storm命令"storm nimbus”来启动看下源码, 此处和上面client不同, jvmtype="-serv ...

  9. JStorm与Storm源码分析(五)--SpoutOutputCollector与代理模式

    本文主要是解析SpoutOutputCollector源码,顺便分析该类中所涉及的设计模式–代理模式. 首先介绍一下Spout输出收集器接口–ISpoutOutputCollector,该接口主要声明 ...

  10. Storm-源码分析-EventManager (backtype.storm.event)

    Protocol and DataType 大体结构, 定义protocol EventManager, 其实就是定义interface 函数event-manager, 主要做2件事 1. 启动ev ...

随机推荐

  1. R内存扩展 win7内存扩展

    安装包 imdiskinst 文件 램디스크 사용http://www.ltr-data.se/ http://cruciancar.blog.me/150101634586 --TEMP 변수 TE ...

  2. 多线程-BlockingQueue,Array[Linked]BlockingQueue,DelayQueue,PriorityBlockingQueue,SynchronousQueue

    阻塞场景 BlockingQueue阻塞队列,阻塞的情况主要有如下2种: 1. 当队列满了,进行入队操作阻塞 2. 当队列空了,进行出队操作阻塞 阻塞队列主要用在生产者/消费者模式中,下图展示了一个线 ...

  3. Vivado 自带IP仿真问题

    可以新建一个测试工程,通过IP catalog直接生产IP核,在IP核上右键选择 Open IP Example Design 之后选择生成路径. 启动Run Simulation.

  4. SVN使用(自己总结)

    1.第一次导入,注意要新建个readme.txt文件用于记录版本更改,每次导入时 要填写import message 2.第二次增加文件导入时 勾选未受控版本文件(新增加文件) 完成上传就可更新增加的 ...

  5. 设置phpcms v9黄页模块作为首页方法

    如果我们根据需要,想把黄页作为单独的网站,我们可以用模块化安装,并且首页设置,那么仿站网就说说详细的步骤.首先,我们需要安装最新版本的phpcms V9其次,下载黄页模块,然后进行根目录的替换.再次, ...

  6. C++语言基础(21)-异常

    C++语言本身或者标准库抛出的异常都是 exception 的子类,称为标准异常(Standard Exception).你可以通过下面的语句来捕获所有的标准异常: try{ //可能抛出异常的语句 ...

  7. makefile之变量

    1 变量的定义 A variable is a name defined in a makefile to represent a string of text, called the variabl ...

  8. PHP 操作SQLite

    连接数据库 下面的 PHP 代码显示了如何连接到一个现有的数据库.如果数据库不存在,那么它就会被创建,最后将返回一个数据库对象. <?php class MyDB extends SQLite3 ...

  9. git三种模式及常用命令

    Git的三种重要模式,分别是已提交.已修改.已暂存. 已提交(committed):表示数据文件已经顺利提交到Git数据库中. 已修改(modified):表示数据文件已经被修改,但未被保存到Git数 ...

  10. nginx调用php-fpm出错解决方法和nginx配置详解

    装完了nginx和php-5.5,配置好了nginx调用php后,就开始启动php-fpm. 使用下面的命令 复制代码 代码如下: /usr/local/php/sbin/php-fpm 就可以启动了 ...