storm学习-1

学习storm入门的例子,100%可运行

源码下载地址:http://download.csdn.net/download/adam_zs/9961426




TopologyMain.java

import spouts.WordReader;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.tuple.Fields;
import bolts.WordCounter;
import bolts.WordNormalizer;

/**
 * @title: 创建拓扑 <br/>
 * @author: wangzs <br/>
 * @date: 2017年9月2日
 */
public class TopologyMain {
	public static void main(String[] args) throws InterruptedException {

		// 定义拓扑: TopologyBuilder 将用来创建拓扑,它决定 Storm 如何安排各节点,以及它们交换数据的方式。
		TopologyBuilder builder = new TopologyBuilder();
		builder.setSpout("word-reader", new WordReader());
		builder.setBolt("word-normalizer", new WordNormalizer()).shuffleGrouping("word-reader");
		builder.setBolt("word-counter", new WordCounter(), 2).fieldsGrouping("word-normalizer", new Fields("word"));

		// 在 spout 和 bolts 之间通过 shuffleGrouping 方法连接。这种分组方式决定了 Storm 会以随机分配方式从源节点向目标节点发送消息。

		// 配置: 创建一个包含拓扑配置的 Config 对象,它会在运行时与集群配置合并,并通过prepare 方法发送给所有节点。
		Config conf = new Config();
		conf.put("wordsFile", "E:/wangzsAi/Getting-Started/src/main/resources/words.txt");
		conf.setDebug(false);
		conf.put(Config.TOPOLOGY_MAX_SPOUT_PENDING, 1);

		// 运行拓扑: 调用 createTopology 和 submitTopology,运行拓扑,休眠两秒钟(拓扑在另外的线程运行),然后关闭集群。
		LocalCluster cluster = new LocalCluster();
		cluster.submitTopology("Getting-Started-Toplogie", conf, builder.createTopology());
		Thread.sleep(1000);
		cluster.shutdown();
	}
}

WordReader.java

package spouts;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Map;

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;

/**
 * @title: WordReader负责从文件按行读取文本,并把文本行提供给第一个 bolt。 <br/>
 * @author: wangzs <br/>
 * @date: 2017年9月2日
 */
public class WordReader extends BaseRichSpout {

	private static final long serialVersionUID = 8659118943517689911L;

	private SpoutOutputCollector collector;
	private FileReader fileReader;
	private boolean completed = false;

	/**
	 * 第一个被调用的spout方法都是open,我们将创建一个文件并维持一个collector对象
	 * 
	 * @param conf
	 *            配置对象,在定义topology对象是创建
	 * @param context
	 *            TopologyContext对象,包含所有拓扑数据
	 * @param collector
	 *            能让我们发布交给 bolts 处理的数据
	 */
	public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
		try {
			this.fileReader = new FileReader(conf.get("wordsFile").toString());
		} catch (FileNotFoundException e) {
			throw new RuntimeException("Error reading file [" + conf.get("wordFile") + "]");
		}
		this.collector = collector;
	}

	/**
	 * 我们要通过nextTuple向 bolts 发布待处理的数据。在这个例子里,这个方法要读取文件并逐行发布数据。
	 */
	public void nextTuple() {
		/**
		 * 这个方法会不断的被调用,直到整个文件都读完了,我们将等待并返回。
		 */
		if (completed) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			return;
		}
		String str;
		BufferedReader reader = new BufferedReader(fileReader);
		try {
			while ((str = reader.readLine()) != null) {
				/**
				 * 按行发布一个新值
				 */
				this.collector.emit(new Values(str), str); // Values 是一个 ArrarList 实现,它的元素就是传入构造器的参数。
			}
		} catch (Exception e) {
			throw new RuntimeException("Error reading tuple", e);
		} finally {
			completed = true;
		}
	}

	// nextTuple() 会在同一个循环内被 ack() 和 fail() 周期性的调用。
	public void ack(Object msgId) {
		System.out.println("OK:" + msgId);
	}

	public void fail(Object msgId) {
		System.out.println("FAIL:" + msgId);
	}

	/**
	 * 声明输入域"line"
	 */
	public void declareOutputFields(OutputFieldsDeclarer declarer) {
		declarer.declare(new Fields("line"));
	}
}

WordNormalizer.java

package bolts;

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;

/**
 * @title: 第一个 bolt,WordNormalizer,负责得到并标准化每行文本。它把文本行切分成单词,大写转化成小写,去掉头尾空白符。 <br/>
 * @author: wangzs <br/>
 * @date: 2017年9月2日
 */
public class WordNormalizer extends BaseBasicBolt {

	private static final long serialVersionUID = 751105854423231360L;

	/**
	 * bolt最重要的方法execute(),每次接收到元组时都会被调用一次,还会再发布若干个元组 <br/>
	 * bolt从单词文件接收到文本行,并标准化它。 文本行会全部转化成小写,并切分它,从中得到所有单词。
	 */
	public void execute(Tuple input, BasicOutputCollector collector) {
		String sentence = input.getString(0);
		String[] words = sentence.split(" ");
		for (String word : words) {
			word = word.trim();
			if (!word.isEmpty()) {
				word = word.toLowerCase();
				// 发布这个单词
				collector.emit(new Values(word));
			}
		}
	}

	/**
	 * 声明 bolt 的出参,这里我们声明 bolt 将发布一个名为 “word” 的域。
	 */
	public void declareOutputFields(OutputFieldsDeclarer declarer) {
		declarer.declare(new Fields("word"));
	}
}

WordCounter.java

package bolts;

import java.util.HashMap;
import java.util.Map;

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;

public class WordCounter extends BaseBasicBolt {

	private static final long serialVersionUID = -2795932943749903797L;

	Integer id;
	String name;
	Map<String, Integer> counters;

	/**
	 * 初始化
	 */
	@Override
	public void prepare(Map stormConf, TopologyContext context) {
		this.counters = new HashMap<String, Integer>();
		this.name = context.getThisComponentId();
		this.id = context.getThisTaskId();
	}

	/**
	 * 为每个单词计数
	 */
	@Override
	public void execute(Tuple input, BasicOutputCollector collector) {
		String str = input.getString(0);
		/**
		 * 如果单词尚不存在于map,我们就创建一个,如果已在,我们就为它加1
		 */
		if (!counters.containsKey(str)) {
			counters.put(str, 1);
		} else {
			Integer c = counters.get(str) + 1;
			counters.put(str, c);
		}
	}

	/**
	 * 这个拓扑结束时(cleanup() 方法被调用时),我们将显示每个单词的数量。
	 */
	@Override
	public void cleanup() {
		System.out.println("-- Word Counter [" + name + "-" + id + "] --");
		for (Map.Entry<String, Integer> entry : counters.entrySet()) {
			System.out.println(entry.getKey() + ": " + entry.getValue());
		}
	}

	@Override
	public void declareOutputFields(OutputFieldsDeclarer declarer) {

	}
}

输出结果:

OK:storm
OK:test
OK:are
OK:great
OK:an
OK:storm
OK:but
OK:really
OK:is
OK:StOrm
OK:simple
OK:application
OK:very
OK:powerfull
OK:
OK:is
OK:great
-- Word Counter [word-counter-2] --
very: 1
test: 1
application: 1
are: 1
is: 2
simple: 1
powerfull: 1
-- Word Counter [word-counter-1] --
but: 1
storm: 3
great: 2
an: 1
really: 1


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值