在Strom/JStorm中有一个类是特别重要的,主要用来构建Topology的,这个类就是TopologyBuilder. 
咱先看一下简单的例子:

public static void main(String[] args) throws AlreadyAliveException,
InvalidTopologyException {
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("input", new RandomSentenceSpout(), 2);
builder.setBolt("bolt_sentence", new SplitSentenceBolt(), 2)
.shuffleGrouping("input"); // 本地模式:最主要用来调试用
LocalCluster cluster = new LocalCluster();
System.out.println("start wordcount");
cluster.submitTopology("word count", conf, builder.createTopology());
}

在上面的main方法里先创建TopologyBuilder对象,然后设置好已创建的Spout节点和Bolt节点,并用随机分组(shuffleGrouping)将Spout和Bolt节点连接起来形成Topology。

那TopologyBuilder是如何做的呢?请看下面TopologyBuilder源代码:

/**
* TopologyBuilder是一个用于构建Topology的工具类
*
*/
public class TopologyBuilder {
/**
* 定义了类成员变量_bolts,用来存放IRichBolt类型的所有Bolt对象
*/
private Map<String, IRichBolt> _bolts = new HashMap<String, IRichBolt>();
/**
* 定义了类成员变量_spouts,用来存放IRichSpout类型的所有Spout对象
*/
private Map<String, IRichSpout> _spouts = new HashMap<String, IRichSpout>();
/**
* 定义了类成员变量_commons,存放了所有的Bolt和Spout对象
*/
private Map<String, ComponentCommon> _commons = new HashMap<String, ComponentCommon>(); // private Map<String, Map<GlobalStreamId, Grouping>> _inputs = new HashMap<String, Map<GlobalStreamId, Grouping>>(); private Map<String, StateSpoutSpec> _stateSpouts = new HashMap<String, StateSpoutSpec>();
/**
* 根据传入的Bolt和Spout对象构建StormTopology对象
* @return
*/
public StormTopology createTopology() {
Map<String, Bolt> boltSpecs = new HashMap<String, Bolt>();
Map<String, SpoutSpec> spoutSpecs = new HashMap<String, SpoutSpec>();
for (String boltId : _bolts.keySet()) {
//根据boltId从_bolts中获取到对应的bolt对象
IRichBolt bolt = _bolts.get(boltId);
//设置对应ComponentCommon对象的streams(输出的字段列表以及是否是直接流)属性值
ComponentCommon common = getComponentCommon(boltId, bolt);
/**
* 先将Bolts对象序列化得到数组,再创建Bolt对象,所以所有在StormTopology中Bolts是对象序列化过后得到的字节数组.
*/
boltSpecs.put(boltId, new Bolt(ComponentObject.serialized_java(Utils.javaSerialize(bolt)), common));
}
for (String spoutId : _spouts.keySet()) {
//根据spoutId从_spouts中获取到对应的spout对象
IRichSpout spout = _spouts.get(spoutId);
//设置对应ComponentCommon对象的streams(输出的字段列表以及是否是直接流)
ComponentCommon common = getComponentCommon(spoutId, spout);
/**
* 先将Spout对象序列化得到数组,再创建SpoutSpec对象,所以所有在StormTopology中Spouts是对象序列化过后得到的字节数组.
*/
spoutSpecs.put(spoutId, new SpoutSpec(ComponentObject.serialized_java(Utils.javaSerialize(spout)), common)); }
//将上述所设置的所有组件都封装到StormTopology对象中,最后提交到集群中运行
return new StormTopology(spoutSpecs, boltSpecs, new HashMap<String, StateSpoutSpec>());
}
/**
* 下面几个方法定义了setBolt方法以及它的重载方法
*/
/**
* 在这个topology中定义一个只有单线程并行度的新的bolt
* 其它想要消耗这个bolt的输出的组件会引用这个id
*/
public BoltDeclarer setBolt(String id, IRichBolt bolt) {
return setBolt(id, bolt, null);
} /**
* 为这个topology定义一个指定数量的并行度的bolt
*/
public BoltDeclarer setBolt(String id, IRichBolt bolt, Number parallelism_hint) {
//检测传入的组件id是否唯一
validateUnusedId(id);
//生成common对象
initCommon(id, bolt, parallelism_hint);
_bolts.put(id, bolt);
return new BoltGetter(id);
} public BoltDeclarer setBolt(String id, IBasicBolt bolt) {
return setBolt(id, bolt, null);
} public BoltDeclarer setBolt(String id, IBasicBolt bolt, Number parallelism_hint) {
/**
* 该方法利用BasicBoltExecutor包装(封装)传入的IBasicBolt对象
* 在BasicBoltExecutor中实现了对消息的追踪
*/
return setBolt(id, new BasicBoltExecutor(bolt), parallelism_hint);
}
/**
* 下面几个方法定义了setSpout方法以及它的重载方法
*/
public SpoutDeclarer setSpout(String id, IRichSpout spout) {
return setSpout(id, spout, null);
} public SpoutDeclarer setSpout(String id, IRichSpout spout, Number parallelism_hint) {
//检测输入的id是否唯一,若已经存在将抛出异常
validateUnusedId(id);
/**
* 构建ComponentCommon对象并进行相对应的初始化,最后放入到_commons(在上述中已经定义)
*/
initCommon(id, spout, parallelism_hint);
_spouts.put(id, spout);
return new SpoutGetter(id);
} public SpoutDeclarer setSpout(String id, IControlSpout spout) {
return setSpout(id, spout, null);
} public SpoutDeclarer setSpout(String id, IControlSpout spout, Number parallelism_hint) {
return setSpout(id, new ControlSpoutExecutor(spout), parallelism_hint);
} public BoltDeclarer setBolt(String id, IControlBolt bolt, Number parallelism_hint) {
return setBolt(id, new ControlBoltExecutor(bolt), parallelism_hint);
}
public BoltDeclarer setBolt(String id, IControlBolt bolt) {
return setBolt(id, bolt, null);
} public void setStateSpout(String id, IRichStateSpout stateSpout) {
setStateSpout(id, stateSpout, null);
}
public void setStateSpout(String id, IRichStateSpout stateSpout, Number parallelism_hint) {
validateUnusedId(id);
// TODO: finish
}
/**
* 检测输入的id是否唯一
* @param id
*/
private void validateUnusedId(String id) {
if (_bolts.containsKey(id)) {
throw new IllegalArgumentException("Bolt has already been declared for id " + id);
}
if (_spouts.containsKey(id)) {
throw new IllegalArgumentException("Spout has already been declared for id " + id);
}
if (_stateSpouts.containsKey(id)) {
throw new IllegalArgumentException("State spout has already been declared for id " + id);
}
} private ComponentCommon getComponentCommon(String id, IComponent component) {
ComponentCommon ret = new ComponentCommon(_commons.get(id)); OutputFieldsGetter getter = new OutputFieldsGetter();
component.declareOutputFields(getter);
ret.set_streams(getter.getFieldsDeclaration());
return ret;
}
/**
* 定义了initCommon方法,用来初始化变量CommonentCommon对象,并给类成员变量_commons赋值
* 初始化所做的工作:设置并行度还有一些其它配置
* @param id
* @param component
* @param parallelism
*/
private void initCommon(String id, IComponent component, Number parallelism) {
ComponentCommon common = new ComponentCommon();
//设置消息流的来源及分组方式
common.set_inputs(new HashMap<GlobalStreamId, Grouping>());
if (parallelism != null) {
//设置并行度
common.set_parallelism_hint(parallelism.intValue());
} else {
//如果并行度没有手动设置则默认为1
common.set_parallelism_hint(1);
}
Map conf = component.getComponentConfiguration();
if (conf != null)
//设置组件的配置参数
common.set_json_conf(JSONValue.toJSONString(conf));
_commons.put(id, common);
}
}

从上面TopologyBuilder的类中可以看到这个类提供了创建StormTopology的方法以及一些数据源节点和处理节点的相关设置的方法,

还有就是存储Bolt对象和Spout对象的方法,当然这里关于分组的代码没有写出来。事实上这个类就是用来设置Spout节点和Bolt节点,

并通过分组方式将Spout和Bolt节点连接起来形成拓扑结构的。

Storm/JStorm之TopologyBuilder源码阅读的更多相关文章

  1. fw: 专访许鹏:谈C程序员修养及大型项目源码阅读与学习

      C家最近也有一篇关于如何阅读大型c项目源代码的文章,学习..融合.. -------------------- ref:http://www.csdn.net/article/2014-06-05 ...

  2. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  3. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  4. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  5. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  6. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  7. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  8. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  9. 【原】AFNetworking源码阅读(二)

    [原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...

随机推荐

  1. Layered Windows窗口的半透明效果

    介绍: Layered Windows是windows窗口中的一类,提供类似半透明的效果(阿尔法混合).半透明效果是字面上有能看出来的,但实际上根据MSND,该类型的窗口还能更好的支持非矩形的窗口,使 ...

  2. 在项目中利用TX Text Control进行WORD文档的编辑显示处理

    在很多文档管理的功能模块里面,我们往往需要对WORD稳定进行展示.编辑等处理,而如果使用微软word控件进行处理,需要安装WORD组件,而且接口使用也不见得简单易用,因此如果有第三方且不用安装Offi ...

  3. 用Nodejs做一个简单的小爬虫

    Nodejs将JavaScript语言带到了服务器端,作为js主力用户的前端们,因此获得了服务器端的开发能力,但除了用express搭建一个博客外,还有什么好玩的项目可以做呢?不如就做一个网络爬虫吧. ...

  4. django ngRoute ui-router 开发环境下禁用缓存

    问题描述: Python manage.py runserver ,禁用缓存,及时修改反馈到浏览器 解决办法: 使用dummy cache: Dummy caching (for developmen ...

  5. Cordova各个插件使用介绍系列(六)—$cordovaDevice获取设备的相关信息

    详情请看:Cordova各个插件使用介绍系列(六)—$cordovaDevice获取设备的相关信息 在项目中需要获取到当前设备,例如手机的ID,联网状态,等,然后这个Cordova里有这个插件可以用, ...

  6. Linux 最新SO_REUSEPORT特性

    1.前言 昨天总结了一下Linux下网络编程“惊群”现象,给出Nginx处理惊群的方法,使用互斥锁.为例发挥多核的优势,目前常见的网络编程模型就是多进程或多线程,根据accpet的位置,分为如下场景: ...

  7. LODOP之票据连续套打笔记<二>

    接着上一篇博文,继续说说关于lodop,关于模板设计及相关的这里不多说了,上一篇博文最下面的推荐可以看看,说的很比较清楚,今天说说我在项目中运用套打实现分页预览和打印的, 之前弄lodop打印的时候发 ...

  8. LaTeX初识 新手入门 Texlive和Texmaker学习

    转载自:http://blog.sina.com.cn/s/blog_90444ed201016iq6.html http://blog.csdn.net/zb1165048017/article/d ...

  9. Example002定时打开窗口

    <!--实例002定时打开窗口--> <script> // 3秒后弹出窗口: function time() { window.open("index.html&q ...

  10. PILLOW图片中加入中文 曲线救国Opencv

    索引 简述 准备 示例 效果图 结语 简述 我在使用opencv2或3的时候想要在图片上添加中文文字,需要去下载Freetype库,编译好链接到opencv库中才能中文的输出.网上大部分在图片中插入中 ...