Storm之——简单编程案例

来源:互联网 发布:植物生长算法代码 编辑:程序博客网 时间:2024/06/04 18:38

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/78336236

一、案例概述

今天,就带着大家一起来实现一个简单的Storm实例,这个实例很简单,实现以下功能:

我们定义一个数组,比如:String[] words = {"iphone","xiaomi","mate","sony","sumsung","moto","meizu"};  通过Strom不断输出类似输出以下的结果:

IPHONE_itisokXIAOMI_itisokMATE_itisokSONY_itisokSUMSUNG_itisokMOTO_itisokMEIZU_itisok
即,通过Storm先将数组中的单词变为大写,然后再后面加上后缀_itisok。

二、实现

1、创建项目

首先我们先创建一个Java工程,并将STORM_HOME/lib目录下的jar包添加到项目的classpath路径下。

2、创建RandomWordSpout类

创建RandomWordSpout类,此类继承backtype.storm.topology.base.BaseRichSpout,主要的功能是,从数组中随机获取元素,并产生消息。

具体代码如下:

package com.lyz.storm.demo;import java.util.Map;import java.util.Random;import backtype.storm.spout.SpoutOutputCollector;import backtype.storm.task.TopologyContext;import backtype.storm.topology.OutputFieldsDeclarer;import backtype.storm.topology.base.BaseRichSpout;import backtype.storm.tuple.Fields;import backtype.storm.tuple.Values;import backtype.storm.utils.Utils;/** * 模拟产生随机商品,产生消息 * @author liuyazhuang * */public class RandomWordSpout extends BaseRichSpout{private static final long serialVersionUID = -5694853370249658735L;private SpoutOutputCollector collector;//模拟一些数据String[] words = {"iphone","xiaomi","mate","sony","sumsung","moto","meizu"};//不断地往下一个组件发送tuple消息//这里面是该spout组件的核心逻辑@Overridepublic void nextTuple() {//可以从kafka消息队列中拿到数据,简便起见,我们从words数组中随机挑选一个商品名发送出去Random random = new Random();int index = random.nextInt(words.length);//通过随机数拿到一个商品名String godName = words[index];//将商品名封装成tuple,发送消息给下一个组件collector.emit(new Values(godName));//每发送一个消息,休眠500msUtils.sleep(500);}//初始化方法,在spout组件实例化时调用一次@Overridepublic void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {this.collector = collector;}//声明本spout组件发送出去的tuple中的数据的字段名@Overridepublic void declareOutputFields(OutputFieldsDeclarer declarer) {declarer.declare(new Fields("orignname"));}}

3、创建UpperBolt类

创建UpperBolt类,此类继承backtype.storm.topology.base.BaseRichSpout,主要的功能是接收RandomWordSpout类产生的消息,并将消息中的单词转化为大写,同时,将单词发送给下一业务逻辑。

具体代码如下:

package com.lyz.storm.demo;import backtype.storm.topology.BasicOutputCollector;import backtype.storm.topology.OutputFieldsDeclarer;import backtype.storm.topology.base.BaseBasicBolt;import backtype.storm.tuple.Fields;import backtype.storm.tuple.Tuple;import backtype.storm.tuple.Values;/** * 将得到的模拟商品名称转化为大写 * @author liuyazhuang * */public class UpperBolt extends BaseBasicBolt{private static final long serialVersionUID = 3968956714937045377L;//业务处理逻辑@Overridepublic void execute(Tuple tuple, BasicOutputCollector collector) {//先获取到上一个组件传递过来的数据,数据在tuple里面String godName = tuple.getString(0);//将商品名转换成大写String godName_upper = godName.toUpperCase();//将转换完成的商品名发送出去collector.emit(new Values(godName_upper));}//声明该bolt组件要发出去的tuple的字段@Overridepublic void declareOutputFields(OutputFieldsDeclarer declarer) {declarer.declare(new Fields("uppername"));}}

4、创建SuffixBolt类

创建SuffixBolt类,此类继承backtype.storm.topology.base.BaseRichSpout,主要的功能是:接收UpperBolt发送的消息,获取单词,并在单词后面添加后缀_itisok,输出的文件。

具体代码如下:

package com.lyz.storm.demo;import java.io.FileWriter;import java.io.IOException;import java.util.Map;import java.util.UUID;import backtype.storm.task.TopologyContext;import backtype.storm.topology.BasicOutputCollector;import backtype.storm.topology.OutputFieldsDeclarer;import backtype.storm.topology.base.BaseBasicBolt;import backtype.storm.tuple.Tuple;/** * 将收到的商品加上后缀"_itisok" * @author liuyazhuang * */public class SuffixBolt extends BaseBasicBolt{private static final long serialVersionUID = 5122871763103743706L;private FileWriter fileWriter = null;//在bolt组件运行过程中只会被调用一次@Overridepublic void prepare(Map stormConf, TopologyContext context) {try {fileWriter = new FileWriter("/usr/local/storm_data/"+UUID.randomUUID());} catch (IOException e) {throw new RuntimeException(e);}}//该bolt组件的核心处理逻辑//每收到一个tuple消息,就会被调用一次@Overridepublic void execute(Tuple tuple, BasicOutputCollector collector) {//先拿到上一个组件发送过来的商品名称String upper_name = tuple.getString(0);//为上一个组件发送过来的商品名称添加后缀String suffix_name = upper_name + "_itisok";try {fileWriter.write(suffix_name);fileWriter.write("\n");fileWriter.flush();} catch (IOException e) {throw new RuntimeException(e);}}//本bolt已经不需要发送tuple消息到下一个组件,所以不需要再声明tuple的字段@Overridepublic void declareOutputFields(OutputFieldsDeclarer arg0) {}}

5、创建TopoMain类

创建TopoMain类,主要的功能是,作为程序启动的入口,同时组织各个处理组件形成一个完整的处理流程,并且将该topology提交给storm集群去运行,topology提交到集群后就将永无休止地运行,除非人为或者异常退出。

具体代码如下:

package com.lyz.storm.demo;import backtype.storm.Config;import backtype.storm.StormSubmitter;import backtype.storm.generated.StormTopology;import backtype.storm.topology.TopologyBuilder;/** * 组织各个处理组件形成一个完整的处理流程,就是所谓的topology(类似于mapreduce程序中的job) * 并且将该topology提交给storm集群去运行,topology提交到集群后就将永无休止地运行,除非人为或者异常退出 * @author liuyazhuang * */public class TopoMain {public static void main(String[] args) throws Exception {TopologyBuilder builder = new TopologyBuilder();//将我们的spout组件设置到topology中去 //parallelism_hint :4  表示用4个excutor来执行这个组件//setNumTasks(8) 设置的是该组件执行时的并发task数量,也就意味着1个excutor会运行2个taskbuilder.setSpout("randomspout", new RandomWordSpout(), 4).setNumTasks(8);//将大写转换bolt组件设置到topology,并且指定它接收randomspout组件的消息//.shuffleGrouping("randomspout")包含两层含义://1、upperbolt组件接收的tuple消息一定来自于randomspout组件//2、randomspout组件和upperbolt组件的大量并发task实例之间收发消息时采用的分组策略是随机分组shuffleGroupingbuilder.setBolt("upperbolt", new UpperBolt(), 4).shuffleGrouping("randomspout");//将添加后缀的bolt组件设置到topology,并且指定它接收upperbolt组件的消息builder.setBolt("suffixbolt", new SuffixBolt(), 4).shuffleGrouping("upperbolt");//用builder来创建一个topologyStormTopology demotop = builder.createTopology();//配置一些topology在集群中运行时的参数Config conf = new Config();//这里设置的是整个demotop所占用的槽位数,也就是worker的数量conf.setNumWorkers(4);conf.setDebug(true);conf.setNumAckers(0);//将这个topology提交给storm集群运行StormSubmitter.submitTopology("demotopo", conf, demotop);}}

三、打包运行

1、创建文件目录

我们在类SuffixBolt中有一行代码如下:

fileWriter = new FileWriter("/usr/local/storm_data/"+UUID.randomUUID());
说明,我们要将结果文件输出到目录/usr/local/storm_data/中,所以,我们首先在服务器上执行如下命令:

mkdir -p /usr/local/storm_data/
类创建文件夹。

2、打包程序

我们将写好的Java工程打包成jar包,比如在Eclipse中导出为Jar包,这个我将这个Jar包的名字定义为storm_test.jar。

3、上传Jar包

这里我直接将Jar包上传到服务器的/usr/local/storm_data/目录下。

4、运行Jar包

我们输入命令:

storm jar storm_test.jar com.lyz.storm.demo.TopoMain
来运行我们的Jar包,此时Storm会提示Jar包已提交到Storm集群,并在服务器的/usr/local/storm_data/下创建了四个随机文件如下:


我们打开其中的一个文件内容如下:


达到了我们的预期效果,注意:这四个文件的内容是不断追加的,除非我们自己手动关闭任务。

至此,这个案例已开发完毕。



原创粉丝点击