标签:
Storm的源码共分为三个不同的层次。
首先,Storm在设计之初就考虑到了兼容多语言开发。Nimbus是一个thrift服务,topologies被定义为Thrift结构体.Thrift的运用使得Storm可以被任意开发语言使用。
其次,Storm的所有接口都是Java语言来定义的。因此,尽管Storm中的很多功能实现都是Clojure代码,但是使用这些功能都必须通过Java API。这意味着Storm的所有特性对于Java来讲都是可用的。
第三,Storm的很大一部分实现都是Clojure代码。从代码行来看,差不多是一半Java代码,一半Clojure代码。但是由于Clojure在表达能力上更为见长,因此,实际上绝大多数逻辑的实现都是Clojure来做的。
接下来的小节里将会逐个详细解释这三个层次。
storm.thrift
要理解Storm的代码结构,首先需要看的是storm.thrift文件。
Storm使用了从这里folk出来的Thrift版本来自动生成代码。这个Thrift版本实际上是将所有的Java packages都重命名为"org.apache.thrift7"之后的Thrift 7。除此之外,它与Thrfit 7是完全一样的。之所以单独出这样一个Thrift版本一是考虑到Thrift缺少向后兼容,而是为了避免包名冲突以满足一些用户在他们自己的topologies中用到其他版本的thrift。
一个topology中的任何一个spout或bolt都会被用户指定一个唯一标识,称为"component id"。当描述1个bolt接收其他哪些spout或bolt的输出时需要用到这个"component id"。StormTopology结构中保存了1个map来保存"component id"到"component"的映射关系,这个映射关系包含所有的component类型(即所有的spout、bolt)。
Thrift对Spout或bolt的定义是相同的,因此我们只需要看一下bolt的thrift定义。它包含了1个"ComponentObject"结构和1个"ComponentCommon"结构。
"ComponentObject"即是bolt的实现实体。它可以是以下三个类型之一:
"ComponentCommon"定义了这个component的其他所有属性。包括:
注意,在spout的结构中同样有"ComponentCommon"字段,因此,spout也是可以被声明接收其他的stream输入。然而,Storm Java API并没有提供一种方式指定spout接收什么stream,同时如果你在这里指定1个spout的输入声明,在提交这个topology时将会出现报错信息。之所以这样设计,是因为spout的输入声明不是让用户自己来使用的,而是Storm内部使用的。Storm会在内部自动向topology添加stream和bolt来构造acking framework,其中的两个stream就是从acker bolt发出给topology中的所有spout节点的。只要1个tuple树被检测到完成了或失败了,acker就会通过这两个stream分别发出"ack"或"fail"消息。将用户提交的topology转换成运行时的topology的代码可参见这里。
Java接口
Storm的接口定义都是Java接口。主要的接口如下:
这样定义这些接口的主要意图在于:
这一策略的实际运用可以参考BaseRichSpout类
Spout和bolt就是按照以上接口描述的方式被序列化到topology的Thrift定义结构中。
值得一提的一个细节是,IBolt、ISpout与IRichBolt、IRichSpout这两对接口是有区别的。它们主要区别是在"Rich"版本里增加了"declareOutputFields"方法。这样设计的原因是所有的输出stream的输出field声明都必须是在Thrift结构里的(这样就可以做到使用任何编程语言来声明了),但是用户又希望能够在自己的class中来声明stream输出field信息。为解决这个问题,"TopologyBuilder"在构造Thrift结构时就是通过调用"declareOutputFields"方法来得到输出field的声明,然后将其转换纳入Thrift结构。这个转换操作可以从"TopologyBuilder"代码中的这一段里看到。
接口实现
通过将Storm所有的接口都由Java语言来定义确保了Storm的所有功能对于Java来讲都是可使用的。同时,Java接口的使用也使得Java用户在使用Storm时体验更好。
应该说,Storm主要是由Clojure语言实现的。尽管从代码行数上看一半是Java一半是Clojure,但其实里面绝大多数的逻辑实现都是Clojure。有两个值得一提的例外就是DRPC和支持事务的topology,它们二者都纯Java实现的。这样做的主要目的是来展示如何基于Storm,实现Storm之上更高层次的抽象。DRPC和支持事务的topology的实现分别位于backtype.storm.coordination和backtype.storm.transactional包里。
这里总结了一份主要的Java包和Clojure命名空间的内容列表:
Java包
Clojure 命名空间
标签:
原文地址:http://www.cnblogs.com/xymqx/p/4374922.html