JStorm中消息确保处理机制
从一个spout发射(emit)出去的元祖(tuple),到达下层bolt时候,可能有bolt拆成多个元祖。这样,元祖从spout出发,经过不同下层bolt的处理变成多个元祖,从而形成了一个以spout为根节点的树形结构。
JStorm会创建并且跟踪从spout发射出去的每一个元祖,当跟踪到在这个树形结构中,所有的叶子节点全被标记处理完毕的时候,才会认为树根节点即从sput发射出去的该元祖成功处理。为了让JStrom创建和跟踪元祖树,我们要做以下两件事情:
- 从bolt里发射新元祖时候,确保anchor to input tuples。
outputCollector.emit(tuple, new Values(order)).
tuple要传的参数。
- bolt处理完元祖要通知JStorm。
outputCollector.ack(tuple);
outputCollector.fail(tuple);
确保消息机制的线程问题:(JStorm wiki)
当topology.max.spout.pending 设置不为1时(包括topology.max.spout.pending设置为null),spout内部将额外启动一个线程单独执行ack或fail操作, 从而nextTuple在单独一个线程中执行,因此允许在nextTuple中执行block动作,而原生的storm,nextTuple/ack/fail 都在一个线程中执行,当数据量不大时,nextTuple立即返回,而ack、fail同样也容易没有数据,进而导致CPU 大量空转,白白浪费CPU, 而在JStorm中, nextTuple可以以block方式获取数据,比如从disruptor中或BlockingQueue中获取数据,当没有数据时,直接block住,节省了大量CPU。
但因此带来一个问题, 处理ack/fail 和nextTuple时,必须小心线程安全性。
附属: 当topology.max.spout.pending为1时, 恢复为spout一个线程,即nextTuple/ack/fail 运行在一个线程中。