一 编程接口

                                         

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmd6aGVianV0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">


Spout 接口

      Spout组件的实现能够通过继承BaseRichSpout类或者其它*Spout类来完毕,也能够通过实现IRichSpout接口来实现。须要依据情况实方法有:


open方法

     当一个Task被初始化的时候会调用此open方法。一般都会在此方法中对发送Tuple的对象SpoutOutputCollector和配置对象TopologyContext初始化。

示比例如以下:

 public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
_collector = collector;
}
declareOutputFields方法

    此方法用于声明当前Spout的Tuple发送流的域名字。Stream流的定义是通过OutputFieldsDeclare.declareStream方法完毕的,当中參数为域名。示比例如以下:
 public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
getComponentConfiguration方法
      此方法定义在BaseComponent类内,用于声明针对当前组件的特殊的Configuration配置。

示比例如以下:

public Map<String, Object> getComponentConfiguration() {
if(!_isDistributed) {
Map<String, Object> ret = new HashMap<String, Object>();
ret.put(Config.TOPOLOGY_MAX_TASK_PARALLELISM, 3);
return ret;
} else {
return null;
}
}

这里便是设置了Topology中当前Component的线程数量上限。

nextTuple方法

    这是Spout类中最重要的一个方法。发射一个Tuple到Topology都是通过这种方法来实现的。示比例如以下:

    public void nextTuple() {
Utils.sleep(100);
final String[] words = new String[] {"twitter","facebook","google"};
final Random rand = new Random();
final String word = words[rand.nextInt(words.length)];
_collector.emit(new Values(word));
}

    这里便是从一个数组中随机选取一个单词作为Tuple,然后通过_collector发送到Topology。

另外。除了上述几个方法之外,还有ack、fail和close方法等。Storm在监測到一个Tuple被成功处理之后会调用ack方法。处理失败会调用fail方法,这两个方法在BaseRichSpout类中已经被隐式的实现了。

Bolts 接口

Bolt类接收由Spout或者其它上游Bolt类发来的Tuple,对其进行处理。Bolt组件的实现能够通过继承BasicRichBolt类或者IRichBolt接口来完毕。Bolt类须要实现的主要方法有:

prepare方法

    此方法和Spout中的open方法类似,为Bolt提供了OutputCollector,用来从Bolt中发送Tuple。

示比例如以下:

public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
}

注:Bolt中Tuple的发送能够在prepare方法中、execute方法中、cleanup等方法中进行,一般都是些在execute中。

declareOutputFields 方法

   用于声明当前Bolt发送的Tuple中包括的字段,和Spout中类似。示比例如以下:

 public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("obj", "count", "length"));
}

此例说明当前Bolt类发送的Tuple包括了三个字段:"obj", "count", "length"。

getComponentConfiguration方法

和Spout类一样,在Bolt中也能够有getComponentConfiguration方法。

示比例如以下:

public Map<String, Object> getComponentConfiguration() {
Map<String, Object> conf = new HashMap<String, Object>();
conf.put(Config.TOPOLOGY_TICK_TUPLE_FREQ_SECS, emitFrequencyInSeconds);
return conf;

此例定义了从系统组件“_system”的“_tick”流中发送Tuple到当前Bolt的频率。当系统须要每隔一段时间运行特定的处理时。就能够利用这个系统的组件的特性来完毕。

execute方法

    这是Bolt中最关键的一个方法,对于Tuple的处理都能够放到此方法中进行。详细的发送也是通过emit方法来完毕的。

此时。有两种情况,一种是emit方法中有两个參数,还有一个种是有一个參数。

     (1) emit有一个參数:此唯一的參数是发送到下游Bolt的Tuple,此时。由上游发来的旧的Tuple在此隔断,新的Tuple和旧的Tuple不再属于同一棵Tuple树。新的Tuple另起一个新的Tuple树。

(2) emit有两个參数:第一个參数是旧的Tuple的输入流,第二个參数是发往下游Bolt的新的Tuple流。此时。新的Tuple和旧的Tuple是仍然属于同一棵Tuple树,即假设下游的Bolt处理Tuple失败。则会向上传递到当前Bolt。当前Bolt依据旧的Tuple流继续往上游传递,申请重发失败的Tuple。保证Tuple处理的可靠性。

这两种情况要依据自己的场景来确定。示比例如以下:

  public void execute(Tuple tuple) {
_collector.emit(tuple, new Values(tuple.getString(0) + "!!!"));
_collector.ack(tuple);
}

注:输入Tuple一般在最后一行被ack

 public void execute(Tuple tuple) {
_collector.emit(new Values(tuple.getString(0) + "!!!"));
}

此外还有ack方法、fail方法、cleanup方法等。当中cleanup方法和Spout中的close方法类似。都是在当前Component关闭时调用,可是针对实时计算来说。除非一些特殊的场景要求以外。这两个方法一般都非常少用到。

    注:cleanup方法在bolt被关闭的时候调用, 它应该清理全部被打开的资源。

可是集群不保证这种方法一定会被运行。

比方运行task的机器down掉了,那么根本就没有办法来调用那个方法。

cleanup设计的时候是被用来在local
mode的时候才被调用(也就是说在一个进程里面模拟整个storm集群), 而且你想在关闭一些topology的时候避免资源泄漏。

有几点须要说明的地方:

    1.每一个组件(Spout或者Bolt)的构造方法和declareOutputFields方法都仅仅被调用一次。

    2.open方法、prepare方法的调用是多次的。入口函数中设定的setSpout或者setBolt里的并行度參数指的是executor的数目,即负责执行组件中的task的线程的数目,此数目是多少。上述的两个方法就会被调用多少次,在每一个executor执行的时候调用一次。相当于一个线程的构造方法。

    3.nextTuple方法、execute方法是一直被执行的,nextTuple方法不断的发射Tuple,Bolt的execute不断的接收Tuple进行处理。仅仅有这样不断地执行。才会产生无界的Tuple流,体现实时性。

    4.在提交了一个topology之后,Storm就会创建spout/bolt实例并进行序列化。之后,将序列化的component发送给全部的任务所在的机器(即Supervisor节点)。在每个任务上反序列化component。

    5. Spout和Bolt之间、Bolt和Bolt之间的通信,是通过zeroMQ的消息队列实现的。

二 作业的提交

   以下的代码展示了以本地执行方式提交一个Topology作业
//Topology definition
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("word-reader",new WordReader());
builder.setBolt("word-normalizer", new WordNormalizer())
.shuffleGrouping("word-reader");
builder.setBolt("word-counter", new WordCount(),1)
.fieldsGrouping("word-normalizer", new Fields("word")); //Configuration
Config conf = new Config();
conf.put("wordsFile", args[0]);
conf.setDebug(true); //Topology run
conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("Getting-Started-Toplogie", conf, builder.createTopology());
Thread.sleep(2000);
cluster.shutdown();
      此例中的builder是TopologyBuilder对象,通过它的createTopology方法能够创建一个Topology对象,同一时候此builder还要定义当前Topology中用到的Spout和Bolt对象,分别通过setSpout方法和setBolt方法来完毕。

setSpout方法和setBolt方法中的第一个參数是当前的Component组件的Stream流ID号;第二个參数是详细的Component实现类的构造;第三个參数是当前Component的并行运行的线程数目,Storm会依据这个数字的累加和来确定Topology的Task数目。


          通过一个LocalCluster对象来定义一个进程内的集群。

提交topology给这个虚拟的集群和提交topology给分布式集群是一样的。

通过调用submitTopology方法来提交topology,
它接受三个參数:要执行的topology的名字,一个配置对象以及要执行的topology本身。


以下对worker、executor以及task做一下说明:

    worker:每一个worker都属于一个特定的Topology,每一个Supervisor节点的worker能够有多个,每一个worker使用一个单独的port,它对Topology中的每一个component执行一个或者多个executor线程来提供task的执行服务。其数目能够通过设置yaml中的topology.workers属性以及在代码中通过Config的setNumWorkers方法设定。

executor:产生于worker进程内部的线程,会运行同一个component的一个或者多个task。 
  其数目能够在Topology的入口类中setBolt、setSpout方法的最后一个參数指定。不指定的话。默觉得1。

task:实际的数据处理由task完毕,在Topology的生命周期中。每一个组件的task数目是不会发生变化的,而executor的数目却不一定。executor数目小于等于task的数目,默认情况下,二者是相等的。在代码中通过TopologyBuilder的setNumTasks方法设定详细某个组件的task数目;

有几点须要说明的地方:

    1.Storm提交后,会把代码首先存放到Nimbus节点的inbox文件夹下,之后,会把当前Storm执行的配置生成一个stormconf.ser文件放到Nimbus节点的stormdist文件夹中,在此文件夹中同一时候还有序列化之后的Topology代码文件;

2.在设定Topology所关联的Spouts和Bolts时。能够同一时候设置当前Spout和Bolt的executor数目和task数目。默认情况下。一个Topology的task的总和是和executor的总和一致的。之后,系统依据worker的数目,尽量平均的分配这些task的执行。

worker在哪个supervisor节点上执行是由storm本身决定的;

3. 任务分配好之后,Nimbes节点会将任务的信息提交到zookeeper集群,同一时候在zookeeper集群中会有workerbeats节点,这里存储了当前Topology的全部worker进程的心跳信息。

4. Supervisor节点会不断的轮询zookeeper集群,在zookeeper的assignments节点中保存了全部Topology的任务分配信息、代码存储文件夹、任务之间的关联关系等。Supervisor通过轮询此节点的内容,来领取自己的任务,启动worker进程执行;

5.一个Topology执行之后。就会不断的通过Spouts来发送Stream流,通过Bolts来不断的处理接收到的Stream流,Stream流是无界的。最后一步会不间断的执行,除非手动结束Topology。

6.通过在Nimbus节点利用例如以下命令来终止一个Topology的执行:storm
kill topologyName kill之后,能够通过UI界面查看topology状态。会首先变成KILLED状态。在清理完本地文件夹和zookeeper集群中的和当前Topology相关的信息之后,此Topology就会彻底消失了。

三 分组策略

1.shuffleGrouping 随机分组
 builder.setBolt("word-normalizer", new WordNormalizer())
           .shuffleGrouping("word-reader");
它仅仅有一个參数(数据源组件),而且数据源会向随机选择的bolt发送元组,保证每一个消费者收到近似数量的元组。

 2.fieldsGrouping 域数据流组
 builder.setBolt("word-counter", new WordCounter(),2)

           .fieldsGrouping("word-normalizer", new Fields("word"));
域数据流组同意你基于元组的一个或多个域控制怎样把元组发送给bolts。它保证拥有同样域组合的值集发送给同一个bolt。

注: 在域数据流组中的全部域集合必须存在于数据源的域声明中

3.allGrouping 所有数据流组 
  builder.setBolt("word-counter", new WordCounter(),2)

           .fieldsGroupint("word-normalizer",new Fields("word"))

           .allGrouping("signals-spout","signals");

全部数据流组。为每一个接收数据的实例复制一份元组副本。这样的分组方式用于向全部bolts发送信号。比方,你要刷新缓存。你能够向全部的bolts发送一个刷新缓存信号。

4.customGrouping  自己定义数据流组
 builder.setBolt("word-normalizer", new WordNormalizer())

           .customGrouping("word-reader", new ModuleGrouping());

5.directGrouping  直接数据流组
  builder.setBolt("word-counter", new WordCounter(),2)

           .directGrouping("word-normalizer");



这是一个特殊的数据流组,数据源能够用它决定哪个组件接收元组。与前面的样例类似。数据源将依据单词首字母决定由哪个bolt接收元组。


6.全局数据流组
全局数据流组把全部数据源创建的元组发送给单一目标实例(即拥有最低ID的任务)。

四 配置选项

在执行Topology之前,能够通过一些參数的配置来调节执行时的状态,參数的配置是通过Storm框架部署文件夹下的conf/storm.yaml文件来完毕的。在此文件里能够配置执行时的Storm本地文件夹路径、执行时Worker的数目等。

       在代码中,也能够设置Config的一些參数。可是优先级是不同的,不同位置配置Config參数的优先级顺序为:

default.yaml < storm.yaml <Topology内部的configuration <内部组件的special configuration < 外部组件的special configuration

在storm.yaml中经常使用的几个选项为:

                                           



版权声明:本文博客原创文章,博客,未经同意,不得转载。

storm-编程入门的更多相关文章

  1. Storm编程入门API系列之Storm的Topology多个Workers数目控制实现

    前期博客 Storm编程入门API系列之Storm的Topology默认Workers.默认executors和默认tasks数目 继续编写 StormTopologyMoreWorker.java ...

  2. Storm编程入门API系列之Storm的Topology多个Executors数目控制实现

    前期博客 Storm编程入门API系列之Storm的Topology默认Workers.默认executors和默认tasks数目 Storm编程入门API系列之Storm的Topology多个Wor ...

  3. Storm编程入门API系列之Storm的Topology多个tasks数目控制实现

    前期博客 Storm编程入门API系列之Storm的Topology默认Workers.默认executors和默认tasks数目 Storm编程入门API系列之Storm的Topology多个Wor ...

  4. Storm编程入门API系列之Storm的定时任务实现

    概念,见博客 Storm概念学习系列之storm的定时任务 Storm的定时任务,分为两种实现方式,都是可以达到目的的. 我这里,分为StormTopologyTimer1.java   和  Sto ...

  5. Storm编程入门API系列之Storm的Topology的stream grouping

    概念,见博客 Storm概念学习系列之stream grouping(流分组) Storm的stream grouping的Shuffle Grouping 它是随机分组,随机派发stream里面的t ...

  6. Storm编程入门API系列之Storm的Topology默认Workers、默认executors和默认tasks数目

    关于,storm的启动我这里不多说了. 见博客 storm的3节点集群详细启动步骤(非HA和HA)(图文详解) 建立stormDemo项目 Group Id :  zhouls.bigdata Art ...

  7. Storm编程入门API系列之Storm的可靠性的ACK消息确认机制

    概念,见博客 Storm概念学习系列之storm的可靠性  什么业务场景需要storm可靠性的ACK确认机制? 答:想要保住数据不丢,或者保住数据总是被处理.即若没被处理的,得让我们知道. publi ...

  8. zookeeper编程入门系列之zookeeper实现分布式进程监控和分布式共享锁(图文详解)

    本博文的主要内容有 一.zookeeper编程入门系列之利用zookeeper的临时节点的特性来监控程序是否还在运行   二.zookeeper编程入门系列之zookeeper实现分布式进程监控 三. ...

  9. 第1节 storm编程:2、storm的基本介绍

    课程大纲: 1.storm的基本介绍 2.storm的架构模型 3.storm的安装 4.storm的UI管理界面 5.storm的编程模型 6.storm的入门程序 7.storm的并行度 8.st ...

  10. PHP面向对象(OOP)编程入门教程

    面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...

随机推荐

  1. iPhone5C三大看点:性能不输iPhone5 或售3399元

    乐杨俊编辑修改转载: iPhone 5C的发售时间或最早在9月18日,抢在中秋节前:最迟至国庆十一假期期间. [IT商业新闻网综合讯](记者 林涛)苹果2013年秋季发布会还有几个小时即将开幕,除了i ...

  2. 有N个正实数(注意是实数,大小升序排列) x1 , x2 ... xN,另有一个实数M。 需要选出若干个x,使这几个x的和与 M 最接近。 请描述实现算法,并指出算法复杂度

    题目:有N个正实数(注意是实数,大小升序排列) x1 , x2 ... xN,另有一个实数M. 需要选出若干个x,使这几个x的和与 M 最接近. 请描述实现算法,并指出算法复杂度. 代码如下: #in ...

  3. HTML学习笔记(七)

    1.       假设想让div中的内容(content)垂直居中,能够将line-height的值设置与div的高度相等来实现. 2.       超伪类链接的四种形式: watermark/2/t ...

  4. 对于面向对象的理解(JAVA)

    JAVA 是一门优美的面向对象的语言.那问题就来了什么是对象,这个问题有一个简单的诠释 “万物皆对象”.那么在面向对象编程中对象是类的一个实例,那么什么是类呢?类是一组相似对象的共有特征的抽象.类有什 ...

  5. spring AOP 是如何一步一步被简化的

    Aop的配置使用 Aop的思想实现是基于代理设计模式的, 动态增加某些功能. 因此在最开始阶段 1 所有需要被织入的类都需要被代理(ProxyFactoryBean). 2 切面(advisor)的实 ...

  6. poj2531

    看了一下0ms,16ms,100ms左右过了的代码,思维量对我来说比較大,不是非常easy理解. 我的作法: 用并查集算权值和. 用dfs枚举两个点集的全部可能,因为是全然图,枚举一半的点就可以. # ...

  7. SQL 2008 数据库迁移

    1,改动迁移路径 USE master GO ALTER DATABASE 数据库名  --主数据 MODIFY FILE(NAME='数据库名', FILENAME='F:\DataBase\数据库 ...

  8. hdu 5014 思维题/推理

    http://acm.hdu.edu.cn/showproblem.php?pid=5014 从小数開始模拟找方法规律,然后推广,尤其敢猜敢尝试,错了一种思路继续猜-----这是一种非常重要的方法啊 ...

  9. JSP自定义标签——简单标签(2)

    在前一篇博客中,我们已经学习了自定义的简单标签的基本使用方法,这一篇我们来学习如何在简单标签中添加标签属性.对自定义标签添加一些属性,可以使我们的标签功能更加灵活和复用.例如前一篇博客使用简单标签来对 ...

  10. VC++ WIN32 sdk实现按钮自绘详解.

    网上找了很多,可只是给出代码,没有详细解释,不便初学者理解.我就抄回冷饭.把这个再拿出来说说. 实例图片:    首先建立一个标准的Win32 Application 工程.选择a simple Wi ...