Apache Storm技术实战之1 -- WordCountTopology
欢迎转载,转载请注意出处,徽沪一郎。
“源码走读系列”从代码层面分析了storm的具体实现,接下来通过具体的实例来说明storm的使用。因为目前storm已经正式迁移到Apache,文章系列也由twitter storm转为apache storm.
WordCountTopology 使用storm来统计文件中的每个单词的出现次数。
通过该例子来说明tuple发送时的几个要素
- source component 发送源
- destination component 接收者
- stream 消息通道
- tuple 消息本身
本文涉及到的开发环境搭建可以参考前面的两篇博文。
awk实现
其实对文件中的单词进行统计是Linux下一个很常见的任务,用awk就可以轻松的解决(如果文件不是太大的话),下面是进行word counting的awk脚本,将其保存为名为wordcount.awk文件。
wordcount.awk
{
for (i = ; i<=NF; i++)
freq[$i]++
}
END{
for (word in freq)
printf "%s\t%d\n",word,freq[word]
}
运行该脚本,对文件中的单词进行统计
gawk -f wordcount.awk filename
原始版本
从github上复制内容
git clone https://github.com/nathanmarz/storm-starter.git
编译运行
lein deps
lein compile
java -cp $(lein classpath) WordCountTopology
main函数
main函数的主要内容
TopologyBuilder builder = new TopologyBuilder();
builder.setSpout("spout", new RandomSentenceSpout(), 5);
builder.setBolt("split", new SplitSentence(), 8).shuffleGrouping("spout");
builder.setBolt("count", new WordCount(), 12).fieldsGrouping("split", new Fields("word"));
注意:grouping操作的时候,如果没有显示指定stream id,则使用的是default stream. 如shuffleGrouping("spout")表示从名为spout的component中接收从default stream发送过来的tuple.
改进版本

在原始版本中,spout不停的向split bolt随机发送句子,Count bolt统计每个单词出现的次数。
那么能不能让Spout在读取完文件之后,通知下游的bolt显示最柊的统计结果呢?
要想达到上述的改进目标,采用如上图所示的结构即可。改变的地方如下,
- 在Spout中添加一个SUCCESS_STREAM
- 添加只有一个运行实例的statistics bolt
- 当spout读取完文件内容之后,通过SUCCESS_STREAM告诉statistics bolt,文件已经处理完毕,可以打印当前的统计结果
RandomSentenceSpout.java
declareOutputFields
添加SUCCESS_STREAM
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
declarer.declareStream("SUCCESS_STREAM",new Fields("word"));
}
nextTuple
使用SUCCESS_STREAM通知下游,文件处理完毕
@Override
public void nextTuple() {
Utils.sleep(100);
String[] sentences = new String[]{ "the cow jumped over the moon", "an apple a day keeps the doctor away",
"four score and seven years ago", "snow white and the seven dwarfs", "i am at two with nature" };
if ( count == sentences.length )
{
System.out.println(count+" try to emit tuple by success_stream");
_collector.emit("SUCCESS_STREAM",new Values(sentences[0]));
count++;
}else if ( count < sentences.length ){
_collector.emit(new Values(sentences[count]));
count++;
}
}
WordCountTopology.java
添加静态类WordCount2
public static class WordCount2 extends BaseBasicBolt {
Map<String, Integer> counts = new HashMap<String, Integer>();
@Override
public void execute(Tuple tuple, BasicOutputCollector collector) {
if ( tuple.getSourceStreamId() == "SUCCESS_STREAM" ) {
System.out.println("prepare to print the statistics");
for (String key : counts.keySet()) {
System.out.println(key+"\t"+counts.get(key));
}
System.out.println("finish printing");
}else {
String word = tuple.getString(0);
Integer count = counts.get(word);
if (count == null)
count = 0;
count++;
counts.put(word, count);
}
}
main函数
将spout的并行数由5改为1
builder.setSpout("spout", new RandomSentenceSpout(), 1);
在原有的Topology中添加WordCount2 Bolt
builder.setBolt("count2", new WordCount2(), 1).globalGrouping("count").globalGrouping("spout","SUCCESS_STREAM");
WordCount2 Bolt会接收从Count Bolt通过default stream发送的tuple,同时接收Spout通过SUCCESS_STREAM发送的tuple,也就是说wordcount2会接收从两个stream来的数据。
编译
编译修改后的源文件
cd $STROM_STARTER
lein compile storm.starter
可能会出现以下异常信息,该异常可以忽略。
Exception in thread "main" java.io.FileNotFoundException: Could not locate storm/starter/WordCountTopology__init.class or storm/starter/WordCountTopology.clj on classpath:
运行
在local模式下运行修改后的WordCountTopology
java -cp $(lein classpath) storm.starter.WordCountTopology
如果一切正常,日志如下所示,线程的名字可能会有所不同。
moon 1
score 1
cow 1
doctor 1
over 1
nature 1
snow 1
four 1
keeps 1
with 1
a 1
white 1
dwarfs 1
at 1
the 4
and 2
i 1
two 1
away 1
seven 2
apple 1
am 1
an 1
jumped 1
day 1
years 1
ago 1
结果验证
可以将WordCountTopology的运行结果和awk脚本的运行结果相比对,结果应该是一致的。
小技巧
- awk脚本的执行结果存为一个文件result1.log, WordCountTopology的输出中单词统计部分存为result2.log
- 用vim打开result1.log,进行sorting,保存结果;用vim打开result2.log,进行sorting,保存。
- 然后用vimdiff来进行比较 vimdiff result1.log result2.log
Apache Storm技术实战之1 -- WordCountTopology的更多相关文章
- Apache Storm技术实战之3 -- TridentWordCount
欢迎转载,转载请注明出处. 介绍TridentTopology的使用,重点分析newDRPCStream和stateQuery的实现机理. 使用TridentTopology进行数据处理的时候,经常会 ...
- Apache Storm技术实战之2 -- BasicDRPCTopology
欢迎转载,转载请注明出处,徽沪一郎. 本文通过BasicDRPCTopology的实例来分析DRPCTopology在提交的时候, Topology中究竟含有哪些内容? BasicDRPCTopolo ...
- Apache Spark技术实战之6 --Standalone部署模式下的临时文件清理
问题导读 1.在Standalone部署模式下,Spark运行过程中会创建哪些临时性目录及文件? 2.在Standalone部署模式下分为几种模式? 3.在client模式和cluster模式下有什么 ...
- Apache Spark技术实战之4 -- 利用Spark将json文件导入Cassandra
欢迎转载,转载请注明出处. 概要 本文简要介绍如何使用spark-cassandra-connector将json文件导入到cassandra数据库,这是一个使用spark的综合性示例. 前提条件 假 ...
- Apache Spark技术实战之3 -- Spark Cassandra Connector的安装和使用
欢迎转载,转载请注明出处,徽沪一郎. 概要 前提 假设当前已经安装好如下软件 jdk sbt git scala 安装cassandra 以archlinux为例,使用如下指令来安装cassandra ...
- Apache Spark技术实战之9 -- 日志级别修改
摘要 在学习使用Spark的过程中,总是想对内部运行过程作深入的了解,其中DEBUG和TRACE级别的日志可以为我们提供详细和有用的信息,那么如何进行合理设置呢,不复杂但也绝不是将一个INFO换为TR ...
- Apache Spark技术实战之8:Standalone部署模式下的临时文件清理
未经本人同意严禁转载,徽沪一郎. 概要 在Standalone部署模式下,Spark运行过程中会创建哪些临时性目录及文件,这些临时目录和文件又是在什么时候被清理,本文将就这些问题做深入细致的解答. 从 ...
- Apache Spark技术实战之7 -- CassandraRDD高并发数据读取实现剖析
未经本人同意,严禁转载,徽沪一郎. 概要 本文就 spark-cassandra-connector 的一些实现细节进行探讨,主要集中于如何快速将大量的数据从cassandra 中读取到本地内存或磁盘 ...
- Apache Spark技术实战之6 -- spark-submit常见问题及其解决
除本人同意外,严禁一切转载,徽沪一郎. 概要 编写了独立运行的Spark Application之后,需要将其提交到Spark Cluster中运行,一般会采用spark-submit来进行应用的提交 ...
随机推荐
- openGL纹理映射参数解析
GLuinttexture[1]; AUX_RGBImageRec *TextureImage[1]; Status=TRUE; // Set The Status To TRUE glGenText ...
- php 数组定义、取值和遍历
<?php //常用函数 //生成随机数 //echo rand(1,10); //两个参数来确定随机数的范围 //日期时间函数 //var_dump(time()); //取当前时间的UNIX ...
- C#学习笔记---如何提高代码逼格
水文.如何让自己的代码看起来,更有逼格? 要想让自己的代码,看起来更优雅,更有逼格,更高大上,就一定要写出晦涩难懂,而又简洁的代码来. 对于类自身的全局变量,一定要加this,对于基类的,一定要加ba ...
- navicat使用跳板机连接数据库-ssh
1. 目标数据库的域名/IP,端口,用户名,密码:如图1 2. 这时候不要点OK!选择SSH这个tab 3. 选中User SSH Tunnel:填写跳板机域名/IP,用户名,密码(注意:端口22不要 ...
- 菜鸟学Linux命令:cat命令 查看文件内容
cat命令的用途是连接文件或标准输入并打印. 这个命令常用来显示文件内容,或者将几个文件连接起来显示,或者从标准输入读取内容并显示,它常与重定向符号配合使用. Linux下查看文件内容的方式很多:vi ...
- 在有EditText控件的AlertDialog对话框中自动弹出输入法
我们先回顾一下创建AlertDialog的一般步骤. 一 inflate AlertDialog的布局文件 例如,其中dlg就是我们的布局文件. View layout = LayoutIn ...
- oracle的启动过程(不分模式启动)
Oracle数据库的完整启动过程包含以下3个步骤: 简单地说,就是:启动实例-->加载数据库-->打开数据库. -------------------------------------- ...
- C# 工程中引用出现感叹号
问题:在工程中引用出现感叹号 原因1: 这是由于之前引用的Dll文件不见了. 右键有感叹号的项,然后选择 “属性” 里边有一个路径属性 这个路径就是之前这个Dll文件的路径,现在这个文件不在了,你需 ...
- mysql错误:“ Every derived table must have its own alias”(每个派生出来的表都必须有一个自己的别名)
自我感悟: 由此可以延伸,我们得到一个结果集,可以通过as XXX的方式,把结果集给当作一张表来用,以实现子查询: 一般在多表查询时,会出现此错误. 因为,进行嵌套查询的时候子查询出来的的结果是作为一 ...
- Eigen相关介绍
最近在用Matlab处理图像,现在要做的是将其用C++语言进行翻译,由于要进行大量的矩阵计算,就研究了一下可以进行矩阵计算的开源库,详细的介绍可以参照http://my.oschina.net/cvn ...