Spout是Storm里面特有的名词, Stream的源头. 通常是从外部数据源读取tuples, 并emit到topology.
Spout可以同时emit多个tuple stream, 通过OutputFieldsDeclarer中的declareStream method来定义
Spout需要实现IRichSpout接口, 最重要的方法是nextTuple, storm会不断调用该接口从spout中取数据
同时需要注意, Spout分为reliable or unreliable两种, 对于reliable, 还支持ack和fail方法, 具体参考"Reliability”
对于Bolt, 用户可以定义任意的处理逻辑, 最重要的方法是execute, 输入为tuple, 输出为emit 0或多个tuples到OutputCollector.
Bolt支持多个输入流和emit多个输出流, 输出流和spout一样, 通过OutputFieldsDeclarer中的declareStream method来定义; 对于输入流, 如果想subscribe上层节点的多个输出streaming, 需要显式的通过stream_id去订阅, 如果不明确指定stream_id, 默认会订阅default stream.
stream 流
可以理解为类似MapReduce job
根本区别, MR job执行完就结束, 而Topology会一直存在. 因为MR流动的是代码, 而Storm流动的数据.
所以Storm不可能替代MR, 因为对于海量数据, 数据的流动是不合理的
另一个区别, 我自己的想法, Topology对工作流有更好的支持, 而MR job往往只能完成一个map/reduce的过程, 而对于复杂的操作, 需要多个MR job才能完成.
而Topology的定义更加灵活, 可以简单的使用一个topology支持比较复杂的工作流场景
Storm Topology是基于Thrift结构, 并且Nimbus是个Thrift server, 所以对于Topology可以用任何语言实现, 最终都是转化为Thrift结构
Topology有一个spout, 两个bolt. setSpout和setBolt的参数都是一样, 分别为id(在Topology中的唯一标识); 处理逻辑(对于Spout就是数据产生function); 并发线程数(task数)
其中对于spout需要实现IRichSpout接口, 而bolt需要实现IRichBolt接口
比较特别的是, setBolt方法会返回一个InputDeclarer对象, 并且该对象是用来定义Bolt输入的, 比如上面.shuffleGrouping(1), 用1(spout)的输出流作为输入
Nimbus和Supervisor之间的所有协调工作都是通过一个Zookeeper集群来完成
nimbus进程和supervisor都是快速失败(fail-fast)和无状态的, 所有的状态都存储在Zookeeper或本地磁盘上
这也就意味着你可以用kill -9来杀死nimbus和supervisor进程, 然后再重启它们, 它们可以继续工作
更重要的是, nimbus和supervisor的fail或restart不会影响worker的工作, 不象Hadoop, Job tracker的fail会导致job失败
如果从task的粒度来看一个运行的topology, 它应该如图, 所以需要策略决定blot和spout, 以及bolt之间的数据流向问题