在$HOME/storm 目录,有 examples 目录,该目录有很多的演示 examples, 特别是 storm-starter 目录下,这个版本兼容其它版本,1.1.0增加 了很多内容, 就连包名都改成了: org. apache.storm 了。
看下面的案例:examples/storm-starter/src/jvm/org/apache/storm/starter/ExclamationTopology.java
下面是整个源代码:
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.storm.starter;
import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.StormSubmitter;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.testing.TestWordSpout;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;
import org.apache.storm.utils.Utils;
import java.util.Map;
/**
* This is a basic example of a Storm topology.
*/
public class ExclamationTopology {
public static class ExclamationBolt extends BaseRichBolt {
OutputCollector _collector;
@Override
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
}
@Override
public void execute(Tuple tuple) {
_collector.emit(tuple, new Values(tuple.getString(0) + "!!!"));
_collector.ack(tuple);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
public static void main(String[] args) throws Exception {
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("word", new TestWordSpout(), 10);
builder.setBolt("exclaim1", new ExclamationBolt(), 3).shuffleGrouping("word");
builder.setBolt("exclaim2", new ExclamationBolt(), 2).shuffleGrouping("exclaim1");
Config conf = new Config();
conf.setDebug(true);
if (args != null && args.length > 0) {
conf.setNumWorkers(3);
StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology());
}
else {
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("test", conf, builder.createTopology());
Utils.sleep(10000);
cluster.killTopology("test");
cluster.shutdown();
}
}
}
ExclamationTopology
的定义:
TopologyBuilder builder = new TopologyBuilder(); builder.setSpout("words", new TestWordSpout(), 10); builder.setBolt("exclaim1", new ExclamationBolt(), 3).shuffleGrouping("words"); builder.setBolt("exclaim2", new ExclamationBolt(), 2).shuffleGrouping("exclaim1");
第一句话:定义 topology
第二句话:设置 Spout。 Spout 产生单词,
第三句话: 设置 Bolt。 在产生单词的基础上加 !!!
第四句话: 设置 Bolt。 在上面继续加 !!
因此,如果 spout 产生 tuples ["bob"]和 ["john"], 第一个 Bolt 将产生["bob!!!"] 和 ["john!!!!"], 第二个 bolt 将产生["bob!!!!!!"] 和 ["john!!!!!!!"]
一、节点定义
setSpout 、setBolt, 其中 id ,在上面例子上被定义为: words, exclaim1 , exclaim2
二、基元的接口
org.apache.storm.topology.TopologyBuilder.setSpout(String, IRichSpout) :SpoutDeclarer
org.apache.storm.topology.TopologyBuilder.setSpout(String, IRichSpout, Number):SpoutDeclarer
org.apache.storm.topology.TopologyBuilder.setBolt(String, IRichBolt):BoltDeclarer
org.apache.storm.topology.TopologyBuilder.setBolt(String, IRichBolt, Number):BoltDeclarer
spout 的处理接口是 IRichSpout 接口, bolt的处理接口是 IRichBolt 接口。最后指定的10,3,2这些都是并行度,是可选的。
三、InputDeclarer对象
setBolt 能返回一个 InputDeclare 对象,这个对象能输入到 Bolt。
比如 ID exclaim1用随机分组(shuffleGrouping)声称它想读组件ID words 产生的所有的元组;
ID exclaim2 用随机分组声明它读 组件ID exclaim1产生的所有的元组。
随机分组(shufflegrouping)意思就是从输入任务到 bolt 任务 中元组能随机分布。随机分组(Shuffle Grouping)是最常用的流分组方式,它随机地分发元组到Bolt上的任务,这样能保证每个任务得到相同数量的元组。在每个 ID 上有很多方法能实现分组,后面会继续解释。
所以,如果组件 ID exclaim2能读组件 ID words 和 exclaim1产生的所有元组,你只需要如下简单定义如下:
builder.setBolt("exclaim2", new ExclamationBolt(), 5)
.shuffleGrouping("words")
.shuffleGrouping("exclaim1");
这个实现起来非常直接简便。
四、ExclamationBolt 实现
ExclamationBolt 就是在输入的元组后面加上三个感叹号“!!!”,完整的实现如下:
public static class ExclamationBolt extends BaseRichBolt {
OutputCollector _collector;
@Override
public void prepare(Map conf, TopologyContext context, OutputCollector collector) {
_collector = collector;
}
@Override
public void execute(Tuple tuple) {
_collector.emit(tuple, new Values(tuple.getString(0) + "!!!"));
_collector.ack(tuple);
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
ExclamationBolt 继承的是基类 BaseRichBolt
prepare 方法用 OutputCollector 类提供了 bolt,并且OutputCollector类就是用来从这个 Bolt 产生元组的,如上的
_collector.emit(tuple, new Values(tuple.getString(0) + "!!!"));
_collector.ack(tuple);
Config conf = new Config();
conf.setDebug(true);
conf.setNumWorkers(2);
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("test", conf, builder.createTopology());
Utils.sleep(10000);
cluster.killTopology("test");
cluster.shutdown();
if (args != null && args.length > 0) {
conf.setNumWorkers(3);
StormSubmitter.submitTopologyWithProgressBar(args[0], conf, builder.createTopology());
这个就是比较简单, 定义 workers 数量为3个,且需要输入指定的参数,就是 Topology 的名字。