Stotm学习笔记一

1 storm入门介绍

1.1 背景-实现实时计算系统需要解决那些问题

如果让我们自己设计一个实时计算系统,我们要解决哪些问题。
(1)低延迟:都说了是实时计算系统了,延迟是一定要低的。
(2)高性能:性能不高就是浪费机器,浪费机器是要受批评的哦。
(3)分布式:系统都是为应用场景而生的,如果你的应用场景、你的数据和计算单机就能搞定,那么不用考虑这些复杂的问题了。我们所说的是单机搞不定的情况。
(4)可扩展:伴随着业务的发展,我们的数据量、计算量可能会越来越大,所以希望这个系统是可扩展的。
(5)容错:这是分布式系统中通用问题。一个节点挂了不能影响我的应用。
(6)通信:设计的系统需要应用程序开发人员考虑各个处理组件的分布、消息的传递吗?如果是,发人员可能会用不好,也不会想去用。
(7)消息不丢失:用户发布的一个宝贝消息不能在实时处理的时候给丢了,对吧?

1.2离线计算是什么

1.3流式计算是什么

流式计算:数据实时产生、数据实时传输、数据实时计算、实时展示
代表技术:Flume实时获取数据、Kafka/metaq实时数据存储、Storm/JStorm实时数据计算、Redis实时结果缓存、持久化存储(mysql)。

1.4离线计算和实时计算的区别

最大的区别:实时收集、实时计算、实时展示
离线计算,一次计算很多条数据
实时计算,数据被一条一条的计算

1.5storm的应用场景

Storm处理数据的方式是基于消息的流水线处理, 因此特别适合无状态计算,也就是计算单元的依赖的数据全部在接受的消息中可以找到, 并且最好一个数据流不依赖另外一个数据流。
因此,常常用于:
1)日志分析,从海量日志中分析出特定的数据,并将分析的结果存入外部存储器用来辅佐决策。
2)管道系统, 将一个数据从一个系统传输到另外一个系统, 比如将数据库同步到Hadoop
3)消息转化器, 将接受到的消息按照某种格式进行转化,存储到另外一个系统如消息中间件
4)统计分析器, 从日志或消息中,提炼出某个字段,然后做count或sum计算,最后将统计值存入外部存储器。中间处理过程可能更复杂。

2storm入门介绍

2.1storm与Hadoop对比性分析storm

1、storm是分布式实时数据计算框架,不负责数据的存储;
   hadoop包含两个框架(hdfs、MapReduce)
2、storm数据的获取:
	Hadoop MapReduce(TextInputFormat\Map\Reduce\TextOutputFormat)由TextInputFormat获取数据
    storm  通过Spout去获取数据,数据可以在数据库中、文件中、redis中等在任何的存储地方。
    注:只有数据实时产生,并实时获取才能让storm实时计算框架产生最大的效益。如果spout在一行一行的读取存储文件中的数据表示只是在实时的读取数据。
3、storm框架数据的实时处理:
	Hadoop MapReduce通关Map\Reduce来计算数据
    storm在Bolt中进行相关业务逻辑的计算,如果有多个阶段的业务逻辑需要计算,将Bolt进行串联,Bolt1--->Bolt2--->Bolt3--->Bolt4 ...
4、storm的编程模型
	Spout--->Bolt1--->Bolt2--->Bolt3---Bolt4...
    获取数据   计算     计算     计算

2.2需求分析(单词统计)

原始数据:i am lilei
        i am hanmeimei
		i am tom
结果数据:i 3
		am 3
        lilei 1
		hanmeimei 1
        tom 1
分析: 1、读取数据,用WordCountSpout组件读取数据
     2、对句子进行分割,SplitBolt进行句子分割
	 3、对单词进行统计并将结果打印出来,CountAndPrintBolt统计单词个数并且打印
流程:WordCountSpout--->SplitBolt--->CountAndPrintBolt
代码:
WordCountSpout:
	package com.storm.wordcount;
	import java.io.IOException;
	import java.io.InputStream;
	import java.util.ArrayList;
	import java.util.List;
	import java.util.Map;
	import org.apache.commons.io.IOUtils;
	import org.apache.commons.io.LineIterator;
	import org.apache.commons.lang.StringUtils;
	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;
	public class WordCountSpout extends BaseRichSpout {
		private static final long serialVersionUID = -1311260628931046774L;
		private SpoutOutputCollector collector;
		private LineIterator lineIterator;
		@SuppressWarnings("rawtypes")
		@Override
		// 初始化方法
		public void open(Map conf, TopologyContext context, SpoutOutputCollector collector) {
			this.collector = collector;
			InputStream in = WordCountSpout.class.getResourceAsStream("/test.dat");
			if (in != null) {
				try {
					this.lineIterator = IOUtils.lineIterator(in, "utf-8");
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		// Storm实时计算的特性就是对数据一条一条的处理
		// while(true){
		// this.nextTuple();
		// }
		@Override
		public void nextTuple() {
			// 每被调用一次就发生一条数据出去
			if (lineIterator != null && lineIterator.hasNext()) {
				String line = lineIterator.nextLine();
				if (StringUtils.isNotEmpty(line)) {
					List<Object> cachingValues = new ArrayList<Object>();
					cachingValues.add(line);
					collector.emit(cachingValues);
					// cachingValues.clear();
				}
			}
		}
		@Override
		public void declareOutputFields(OutputFieldsDeclarer declarer) {
			declarer.declare(new Fields("line"));
		}
	}
SplitBolt:
		package com.storm.wordcount;
		import org.apache.commons.lang.StringUtils;
		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;
		public class SplitBolt extends BaseBasicBolt {
			private static final long serialVersionUID = -3325717180080513451L;
			@Override
			public void execute(Tuple tuple, BasicOutputCollector collector) {
				// 1、如何取数据
				String pickLine = tuple.getStringByField("line");
				if (StringUtils.isNotEmpty(pickLine)) {
					// 2、进行分割
					String[] splitStrs = pickLine.split(" ");
					for (String str : splitStrs) {
						// 3.发送数据
						// values对象会帮助我们生成一个list
						collector.emit(new Values(str, 1));
					}
				}
			}
			@Override
			public void declareOutputFields(OutputFieldsDeclarer declarer) {
				declarer.declare(new Fields("word", "num"));
			}
		}
CountAndPrintBolt:
	package com.storm.wordcount;
	import java.util.HashMap;
	import java.util.Map;
	import org.apache.commons.lang.StringUtils;
	import backtype.storm.topology.BasicOutputCollector;
	import backtype.storm.topology.OutputFieldsDeclarer;
	import backtype.storm.topology.base.BaseBasicBolt;
	import backtype.storm.tuple.Tuple;
	public class CountAndPrintBolt extends BaseBasicBolt {
		private static final long serialVersionUID = 3538707571695237510L;
		private Map<String, Integer> word2Num = new HashMap<String, Integer>();
		@Override
		public void execute(Tuple tuple, BasicOutputCollector collector) {
			String pickWord = tuple.getStringByField("word");
			Integer pickNum = tuple.getIntegerByField("num");
			if (StringUtils.isNotEmpty(pickWord) && pickNum != null) {
				// 查看单词是否存在
				Integer num = word2Num.get(pickWord);
				if (num == null || num.intValue() == 0) {
					word2Num.put(pickWord, pickNum);
				} else {
					word2Num.put(pickWord, pickNum.intValue() + num.intValue());
				}
				// 打印数据
				System.out.println(word2Num);
			}
		}
		@Override
		public void declareOutputFields(OutputFieldsDeclarer declarer) {
			//nothing to do
		}
	}
WordCountTopologyDriver:
	package com.storm.wordcount;
	import backtype.storm.Config;
	import backtype.storm.LocalCluster;
	import backtype.storm.StormSubmitter;
	import backtype.storm.generated.AlreadyAliveException;
	import backtype.storm.generated.InvalidTopologyException;
	import backtype.storm.generated.StormTopology;
	import backtype.storm.topology.TopologyBuilder;
	public class WordCountTopologyDriver {
	public static void main(String[] args) throws AlreadyAliveException, InvalidTopologyException {
		// 1、准备任务信息
		TopologyBuilder builder = new TopologyBuilder();
		builder.setSpout("word_count_spout", new WordCountSpout());
		builder.setBolt("split_bolt", new SplitBolt()).shuffleGrouping("word_count_spout");
		builder.setBolt("count_and_print_bolt", new CountAndPrintBolt()).shuffleGrouping("split_bolt");
		// 2、提交任务
		Config stormConf = new Config();
		StormTopology topology = builder.createTopology();
		// 2.1提交本地模式
//		LocalCluster localCluster = new LocalCluster();
//		localCluster.submitTopology("wordcount", stormConf, topology);
		//2.2集群模式
		StormSubmitter.submitTopology("wordcount", stormConf, topology);
	}
}
posted @ 2017-01-12 13:42  我亦在  阅读(553)  评论(0编辑  收藏  举报