提交示例代码:

public static void main(String[] args) throws Exception {
    TopologyBuilder builder = new TopologyBuilder();
    builder.setSpout("random"new RandomWordSpout(), 2);
    builder.setBolt("transfer"new TransferBolt(), 4).shuffleGrouping("random");
    builder.setBolt("writer"new WriterBolt(), 4).fieldsGrouping("transfer"new Fields("word"));
    Config conf = new Config();
    conf.setNumWorkers(4);// 设置启动4个Worker
    conf.setNumAckers(1); // 设置一个ack线程
    conf.setDebug(true); // 设置打印所有发送的消息及系统消息
10      StormSubmitter.submitTopology("test", conf, builder.createTopology());
11  }
 

1、构建 TopologyBuilder 对象 builder,主要用于对各个组件(bolt、spout)进行配置,TopologyBuilder主要属性字段定义如下:

public class TopologyBuilder {
 
    // 所提交Topolog中所有的bolt将放入到_bolts中
    private Map<String, IRichBolt> _bolts = new HashMap<String, IRichBolt>();
 
    // 所提交Topolog中所有的spout将放入到_spouts中
    private Map<String, IRichSpout> _spouts = new HashMap<String, IRichSpout>();
 
    // 所提交Topolog中所有的spout和bolt都将放入_commons中
10      private Map<String, ComponentCommon> _commons = new HashMap<String, ComponentCommon>();
11   
12      ....................................
13  }
14   

 

2、以上提交代码中第三行,配置了一个id值为random,IRichSpout对象为RandomWordSpout,而并行度为2(两个线程里面跑两个任务)的spout, setSpout函数实现源码如下:

public SpoutDeclarer setSpout(String id, IRichSpout spout, Number parallelism_hint) {
 
    validateUnusedId(id);
 
    initCommon(id, spout, parallelism_hint);
 
    _spouts.put(id, spout);
 
    return new SpoutGetter(id);
10   
11  }
12   

validateUnusedId:检测输入的id是不是唯一,若已经存在将抛出异常;

initCommon:构建ComponentCommon对象并进行相应的初始化,最后放入到_commons(以上TopologyBuilder中定义的Map);

initCommon函数实现源码:

private void initCommon(String id, IComponent component, Number parallelism) {
 
    ComponentCommon common = new ComponentCommon();
 
    // 设置消息流的来源及分组方式
 
    common.set_inputs(new HashMap<GlobalStreamId, Grouping>());
 
    if(parallelism!=null
10   
11      // 设置并行度
12      common.set_parallelism_hint(parallelism.intValue());
13   
14      Map conf = component.getComponentConfiguration();
15   
16      if(conf!=null
17   
18      // 设置组件的配置参数
19      common.set_json_conf(JSONValue.toJSONString(conf));
20   
21      _commons.put(id, common);
22  }

在ComponentCommon中主要对以下四个属性字段进行设置:

GlobalStreamId:确定消息来源,其中componentId表示所属组件,streamId为消息流的标识符;

Grouping:确定消息分组方式;

private Map<GlobalStreamId,Grouping> inputs;

StreamInfo表示输出的字段列表及是否为直接流

private Map<String,StreamInfo> streams;

private int parallelism_hint; // 设置并行度

private String json_conf; // 其它配置参数设置(必须为JSON格式)

 

3、SpoutGetter实现源码:

protected class SpoutGetter extends ConfigGetter<SpoutDeclarer> implements SpoutDeclarer {
 
    public SpoutGetter(String id) {
        super(id);
    }
}

ConfigGetter、SpoutGetter的实现都是在TopologyBuilder中, ConfigGetter作用:设置程序中的配置项,覆盖默认的配置项,且配置项的格式为为JSON(本质上是改变对应ComponentCommon对象中json_conf的值);

 

4、提交示例代码中的第四行定义了一个id为transfer,IRichSpout对象为TransferBolt,并行度为4的bolt

setBolt实现源码:

public BoltDeclarer setBolt(String id, IRichBolt bolt, Number parallelism_hint) {
 
    validateUnusedId(id);
 
    initCommon(id, bolt, parallelism_hint);
 
    _bolts.put(id, bolt);
 
    return new BoltGetter(id);
10   
11  }
12   

设置Bolt的函数与设置Spout函数的实现唯一的区别在返回结果;

BoltGetter实现部分源码:

protected class BoltGetter extends ConfigGetter<BoltDeclarer> implements BoltDeclarer {
 
    private String _boltId;
 
    public BoltGetter(String boltId) {
   
        super(boltId);
   
        _boltId = boltId;
10     
11      }
12     
13      public BoltDeclarer shuffleGrouping(String componentId) {
14     
15          return shuffleGrouping(componentId, Utils.DEFAULT_STREAM_ID);
16     
17      }
18     
19      public BoltDeclarer fieldsGrouping(String componentId, Fields fields) {
20     
21          return fieldsGrouping(componentId, Utils.DEFAULT_STREAM_ID, fields);
22     
23      }
24     
25      public BoltDeclarer fieldsGrouping(String componentId, String streamId, Fields fields) {
26     
27          return grouping(componentId, streamId, Grouping.fields(fields.toList()));
28     
29      }
30     
31      public BoltDeclarer shuffleGrouping(String componentId, String streamId) {
32     
33          return grouping(componentId, streamId, Grouping.shuffle(new NullStruct()));
34     
35      }
36     
37      private BoltDeclarer grouping(String componentId, String streamId, Grouping grouping) {
38     
39          _commons.get(_boltId).put_to_inputs(new GlobalStreamId(componentId, streamId), grouping);
40     
41          return this;
42     
43      }
44   
45      .........................................
46   
47  }
48   

BoltGetter继承至ConfigGetter并实现了BoltDeclarer接口,并重载了BoltDeclarer(InputDeclarer)中各种分组方式(如:fieldsGrouping、shuffleGrouping),分组方式的实现本质上是在_commons中通过对用的boltId找到对应的ComponentCommon对象,对inputs属性进行设置;

 

5、通过以上几步完成了bolt与spout的配置(对应提交示例代码中的2~5行),6~9行是对运行环境的配置,10行用于向集群提交执行任务,builder.createTopology用于构建StormTopology对象,createTopology实现源码如下:

public StormTopology createTopology() {
 
    Map<String, Bolt> boltSpecs = new HashMap<String, Bolt>();
   
    Map<String, SpoutSpec> spoutSpecs = new HashMap<String, SpoutSpec>();
   
    for(String boltId: _bolts.keySet()) {
   
        IRichBolt bolt = _bolts.get(boltId);
10     
11          ComponentCommon common = getComponentCommon(boltId, bolt);
12     
13          boltSpecs.put(boltId, new Bolt(ComponentObject.serialized_java(Utils.serialize(bolt)), common));
14     
15      }
16     
17      for(String spoutId: _spouts.keySet()) {
18     
19          IRichSpout spout = _spouts.get(spoutId);
20     
21          ComponentCommon common = getComponentCommon(spoutId, spout);
22     
23          spoutSpecs.put(spoutId, new SpoutSpec(ComponentObject.serialized_java(Utils.serialize(spout)), common));
24     
25      }
26     
27      return new StormTopology(spoutSpecs,boltSpecs,new HashMap<String, StateSpoutSpec>());
28   
29  }
30   
31   

 

以上源码实现中主要做了两件事:

  • 通过boltId从_bolts中获取到对应的bolt对象,再通过getComponentCommon方法设置对应ComponentCommon对象的streams(输出的字段列表及是否为直接流)属性值,最后将bolt和common一起 放入到boltSpecs集合中。
  • 通过spoutId从_spouts中获取到对应的spout对象,再通过getComponentCommon方法设置对应ComponentCommon对象的streams(输出的字段列表及是否为直接流)属性值,最后将spout和common一起 放入到boltSpecs集合中。
  • 通过以上两步使所设置的所有组件都封装到StormTopology对象中,最后提交的到集群中运行。

Storm系列(三)Topology提交过程的更多相关文章

  1. Storm系列(四)Topology提交校验过程

    功能:提交一个新的Topology,并为Topology创建storm-id(topology-id),校验其结构,设置必要的元数据,最后为Topology分配任务. 实现源码: 1  ); Conf ...

  2. Storm系列三: Storm消息可靠性保障

    Storm系列三: Storm消息可靠性保障 在上一篇 Storm系列二: Storm拓扑设计 中我们已经设计了一个稍微复杂一点的拓扑. 而本篇就是在上一篇的基础上再做出一定的调整. 在这里先大概提一 ...

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

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

  4. Storm系列(三):创建Maven项目打包提交wordcount到Storm集群

    在上一篇博客中,我们通过Storm.Net.Adapter创建了一个使用Csharp编写的Storm Topology - wordcount.本文将介绍如何编写Java端的程序以及如何发布到测试的S ...

  5. Storm 系列(三)Storm 集群部署和配置

    Storm 系列(二)Storm 集群部署和配置 本章中主要介绍了 Storm 的部署过程以及相关的配置信息.通过本章内容,帮助读者从零开始搭建一个 Storm 集群. 一.Storm 的依赖组件 1 ...

  6. Storm 系列(六)—— Storm 项目三种打包方式对比分析

    一.简介 在将 Storm Topology 提交到服务器集群运行时,需要先将项目进行打包.本文主要对比分析各种打包方式,并将打包过程中需要注意的事项进行说明.主要打包方式有以下三种: 第一种:不加任 ...

  7. Storm Topology 提交 总结---Kettle On Storm 实现

    一,目的 在学习的过程中,需要用到 PDI---一个开源的ETL软件.主要是用它来设计一些转换流程来处理数据.但是,在PDI中设计好的 transformation 是在本地的执行引擎中执行的,(参考 ...

  8. Storm概念学习系列之Topology拓扑

    不多说,直接上干货!   Hadoop 上运行的是 MapReduce 作业,而在 Storm 上运行的是拓扑 Topology,这两者之间是非常不同的.一个关键的区别是:一个MapReduce 作业 ...

  9. storm源码剖析(3):topology启动过程

    storm的topology启动过程是执行strom jar topology1.jar MAINCLASS ARG1 ARG2 鉴于前面已经分析了脚本的解析过程,现在重点分析topology1.ja ...

随机推荐

  1. Django环境搭建和项目创建

    1.下载安装python 2.打开shell(windows下cmd),安装虚拟环境工具:  "pip install virtualenv".(可以通过“python -m pi ...

  2. extern "C"的作用

    一.概述 在C语言的头文件中,经常可以看到如下的代码,那这个是什么作用呢? #ifdef __cplusplus extern "C" { #endif /*...*/ #ifde ...

  3. 个人作业-Homework1感想

    我以前没有系统学习过C++和C#,编程能力比较差.这次个人作业对我来说是一个很大的挑战.由于布置作业的时间是开学的第一周,因为还没有从假期的状态中转换出来,这对我写作业又增加了一定的难度. 在开始写作 ...

  4. JavaScript的OOP编程2

    我做了一个observer的设计模式实现 version1 // -------------------------------------------------- function Subject ...

  5. BT5之配置笔记

    BT5本来就是用Ubuntu 10.04做得蓝本,所以,我在配置BT5的时候,基本上都是按照Ubuntu 10.04的配置方法,在配置BT5 1    系统基本设置 1.1  安装Ubuntu10.0 ...

  6. php 数组指针相关函数current(),next(),prev(),end()

    mixed current(array target_array) current()函数返回位于target_array数组当前指针位置的数组值.与next().prev().和end()函数不同, ...

  7. ANDROID_MARS学习笔记_S01原始版_023_MP3PLAYER005_用广播BroacastReciever实现后台播放不更新歌词

    一.代码流程1.自定义一个AppConstant.LRC_MESSAGE_ACTION字符串表示广播"更新歌词" 2.在PlayerActivity的onResume()注册Bro ...

  8. 上海CEC大收购(包括华大九天)

    紫光收购展讯.锐迪科后,上海开始通过扶植CEC培育新势力,CEC已经收购上海澜起,即将收购amlogic.Ominivision,还在与marvell眉来眼去,此外华大九天已经移植上海,加上之前的上海 ...

  9. 归纳决策树ID3(Java实现)

    先上问题吧,我们统计了14天的气象数据(指标包括outlook,temperature,humidity,windy),并已知这些天气是否打球(play).如果给出新一天的气象指标数据:sunny,c ...

  10. bzoj1103

    其实这道题和以前在poj上做过的将树映射到树状数组的题目很像 首先不难想到,将一条边从土路修成公路,只对以这条边连接的孩子结点为根的子树有影响: 于是和之前那道poj的题目很像,后序遍历树,对每个节点 ...