【本篇文章主要是通过一个单词计数的案例学习,来加深对storm的基本概念的理解以及基本的开发流程和如何提交并运行一个拓扑】

  单词计数拓扑WordCountTopology实现的基本功能就是不停地读入一个个句子,最后输出每个单词和数目并在终端不断的更新结果,拓扑的数据流如下:

  

  • 语句输入Spout:  从数据源不停地读入数据,并生成一个个句子,输出的tuple格式:{"sentence":"hello world"}
  • 语句分割Bolt: 将一个句子分割成一个个单词,输出的tuple格式:{"word":"hello"}  {"word":"world"}
  • 单词计数Bolt: 保存每个单词出现的次数,每接到上游一个tuple后,将对应的单词加1,并将该单词和次数发送到下游去,输出的tuple格式:{"hello":"1"}  {"world":"3"}
  • 结果上报Bolt: 维护一份所有单词计数表,每接到上游一个tuple后,更新表中的计数数据,并在终端将结果打印出来。

  开发步骤:

1.环境

  • 操作系统:mac os 10.10.3
  • JDK: jdk1.8.0_40
  • IDE: intellij idea 15.0.3
  • Maven: apache-maven-3.0.3

  2.项目搭建

  • 在idea新建一个maven项目工程:storm-learning
  • 修改pom.xml文件,加入strom核心的依赖,配置slf4j依赖,方便Log输出
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency> <dependency>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>

 3. Spout和Bolt组件的开发

  • SentenceSpout
  • SplitSentenceBolt
  • WordCountBolt
  • ReportBolt

SentenceSpout.java

 public class SentenceSpout extends BaseRichSpout{

     private SpoutOutputCollector spoutOutputCollector;

     //为了简单,定义一个静态数据模拟不断的数据流产生
private static final String[] sentences={
"The logic for a realtime application is packaged into a Storm topology",
"A Storm topology is analogous to a MapReduce job",
"One key difference is that a MapReduce job eventually finishes whereas a topology runs forever",
" A topology is a graph of spouts and bolts that are connected with stream groupings"
}; private int index=0; //初始化操作
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
this.spoutOutputCollector = spoutOutputCollector;
} //核心逻辑
public void nextTuple() {
spoutOutputCollector.emit(new Values(sentences[index]));
++index;
if(index>=sentences.length){
index=0;
}
} //向下游输出
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("sentences"));
}
}

SplitSentenceBolt.java

 public class SplitSentenceBolt extends BaseRichBolt{

     private OutputCollector outputCollector;

     public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.outputCollector = outputCollector;
} public void execute(Tuple tuple) {
String sentence = tuple.getStringByField("sentences");
String[] words = sentence.split(" ");
for(String word : words){
outputCollector.emit(new Values(word));
}
} public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("word"));
}
}

WordCountBolt.java

 public class WordCountBolt extends BaseRichBolt{

     //保存单词计数
private Map<String,Long> wordCount = null; private OutputCollector outputCollector; public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
this.outputCollector = outputCollector;
wordCount = new HashMap<String, Long>();
} public void execute(Tuple tuple) {
String word = tuple.getStringByField("word");
Long count = wordCount.get(word);
if(count == null){
count = 0L;
}
++count;
wordCount.put(word,count);
outputCollector.emit(new Values(word,count));
} public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("word","count"));
}
}

ReportBolt.java

 public class ReportBolt extends BaseRichBolt {

     private static final Logger log = LoggerFactory.getLogger(ReportBolt.class);

     private Map<String, Long> counts = null;

     public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
counts = new HashMap<String, Long>();
} public void execute(Tuple tuple) {
String word = tuple.getStringByField("word");
Long count = tuple.getLongByField("count");
counts.put(word, count);
//打印更新后的结果
printReport();
} public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
//无下游输出,不需要代码
} //主要用于将结果打印出来,便于观察
private void printReport(){
log.info("--------------------------begin-------------------");
Set<String> words = counts.keySet();
for(String word : words){
log.info("@report-bolt@: " + word + " ---> " + counts.get(word));
}
log.info("--------------------------end---------------------");
}
}

 4.拓扑配置

  • WordCountTopology
 public class WordCountTopology {

     private static final Logger log = LoggerFactory.getLogger(WordCountTopology.class);

     //各个组件名字的唯一标识
private final static String SENTENCE_SPOUT_ID = "sentence-spout";
private final static String SPLIT_SENTENCE_BOLT_ID = "split-bolt";
private final static String WORD_COUNT_BOLT_ID = "count-bolt";
private final static String REPORT_BOLT_ID = "report-bolt"; //拓扑名称
private final static String TOPOLOGY_NAME = "word-count-topology"; public static void main(String[] args) { log.info(".........begining.......");
//各个组件的实例
SentenceSpout sentenceSpout = new SentenceSpout();
SplitSentenceBolt splitSentenceBolt = new SplitSentenceBolt();
WordCountBolt wordCountBolt = new WordCountBolt();
ReportBolt reportBolt = new ReportBolt(); //构建一个拓扑Builder
TopologyBuilder topologyBuilder = new TopologyBuilder(); //配置第一个组件sentenceSpout
topologyBuilder.setSpout(SENTENCE_SPOUT_ID, sentenceSpout, 2); //配置第二个组件splitSentenceBolt,上游为sentenceSpout,tuple分组方式为随机分组shuffleGrouping
topologyBuilder.setBolt(SPLIT_SENTENCE_BOLT_ID, splitSentenceBolt).shuffleGrouping(SENTENCE_SPOUT_ID); //配置第三个组件wordCountBolt,上游为splitSentenceBolt,tuple分组方式为fieldsGrouping,同一个单词将进入同一个task中(bolt实例)
topologyBuilder.setBolt(WORD_COUNT_BOLT_ID, wordCountBolt).fieldsGrouping(SPLIT_SENTENCE_BOLT_ID, new Fields("word")); //配置最后一个组件reportBolt,上游为wordCountBolt,tuple分组方式为globalGrouping,即所有的tuple都进入这一个task中
topologyBuilder.setBolt(REPORT_BOLT_ID, reportBolt).globalGrouping(WORD_COUNT_BOLT_ID); Config config = new Config(); //建立本地集群,利用LocalCluster,storm在程序启动时会在本地自动建立一个集群,不需要用户自己再搭建,方便本地开发和debug
LocalCluster cluster = new LocalCluster(); //创建拓扑实例,并提交到本地集群进行运行
cluster.submitTopology(TOPOLOGY_NAME, config, topologyBuilder.createTopology());
}
}

5.拓扑执行

  • 方法一:通过IDEA执行

  在idea中对代码进行编译compile,然后run;

  观察控制台输出会发现,storm首先在本地自动建立了运行环境,即启动了zookepeer,接着启动nimbus,supervisor;然后nimbus将提交的topology进行分发到supervisor,supervisor启动woker进程,woker进程里利用Executor来运行topology的组件(spout和bolt);最后在控制台发现不断的输出单词计数的结果。

     zookepeer的连接建立

   nimbus启动

   supervisor启动

   worker启动

     Executor启动执行

     结果输出

  • 方法二:通过maven来执行

    • 进入到该项目的主目录下:storm-learning
    • mvn compile 进行代码编译,保证代码编译通过
    • 通过mvn执行程序:
      mvn exec:java -Dexec.mainClass="wordCount.WordCountTopology"
    • 控制台输出的结果跟方法一一致

Storm入门2-单词计数案例学习的更多相关文章

  1. 大数据学习——Storm学习单词计数案例

    需求:计算单词在文档中出现的次数,每出现一次就累加一次 遇到的问题 这个问题是<scope>provided</scope>作用域问题 https://www.cnblogs. ...

  2. 2.Storm集群部署及单词统计案例

    1.集群部署的基本流程 2.集群部署的基础环境准备 3.Storm集群部署 4.Storm集群的进程及日志熟悉 5.Storm集群的常用操作命令 6.Storm源码下载及目录熟悉 7.Storm 单词 ...

  3. Storm实现单词计数

    package com.mengyao.storm; import java.io.File; import java.io.IOException; import java.util.Collect ...

  4. hadoop笔记之MapReduce的应用案例(WordCount单词计数)

    MapReduce的应用案例(WordCount单词计数) MapReduce的应用案例(WordCount单词计数) 1. WordCount单词计数 作用: 计算文件中出现每个单词的频数 输入结果 ...

  5. storm(5)-分布式单词计数例子

    例子需求: spout:向后端发送{"sentence":"my dog has fleas"}.一般要连数据源,此处简化写死了. 语句分割bolt(Split ...

  6. 【Storm】storm安装、配置、使用以及Storm单词计数程序的实例分析

    前言:阅读笔记 storm和hadoop集群非常像.hadoop执行mr.storm执行topologies. mr和topologies最关键的不同点是:mr执行终于会结束,而topologies永 ...

  7. storm入门基础实例(无可靠性保证实例)

    本实例为入门篇无可靠性保证实例,关于storm的介绍,以及一些术语名词等,可以参考Storm介绍(一).Storm介绍(二). 本案例是基于storm0.9.3版本 1.案例结构 案例:Word Co ...

  8. Storm入门之第一章

    Storm入门之第一章 1.名词 spout龙卷,读取原始数据为bolt提供数据 bolt雷电,从spout或者其他的bolt接收数据,并处理数据,处理结果可作为其他bolt的数据源或最终结果 nim ...

  9. 大数据【四】MapReduce(单词计数;二次排序;计数器;join;分布式缓存)

       前言: 根据前面的几篇博客学习,现在可以进行MapReduce学习了.本篇博客首先阐述了MapReduce的概念及使用原理,其次直接从五个实验中实践学习(单词计数,二次排序,计数器,join,分 ...

随机推荐

  1. NGINX 配置 SSL 双向认证

    对于 NGINX 的 HTTPS 配置,通常情况下我们只需要实现服务端认证就行,因为浏览器内置了一些受信任的证书颁发机构(CA),服务器端只需要拿到这些机构颁发的证书并配置好,浏览器会自己校验证书的可 ...

  2. 纯手写SpringMVC架构,用注解实现springmvc过程

    1.第一步,首先搭建如下架构,其中,annotation中放置自己编写的注解,主要包括service controller qualifier RequestMapping 第二步:完成对应的anno ...

  3. Log4Net组件的应用详解

    第一步: 添加并应用Log4net.dll.然后在Web.config文件中添加下面的配置局 <configSections>    <section name="log4 ...

  4. 如何查看当前使用的Entity Framework版本

    Visual Studio 中-----工具-----NuGet套件管理员-----套件管理器控制台-----输入Get-Package即可查看当前使用的版本信息

  5. Windows Server 2008 R2安装子域控制器

    一.实验网络拓扑图: 二.实验说明: 子域控制器安装前需要先把主域控制器安装好,然后子域控制器的DNS先指向主域控制器的IP地址 192.168.10.30,主域控制器委派DNS给子域控制器后再把子域 ...

  6. 2.C语言中的关键字

    1.auto 修饰局部变量,编译器默认所有局部变量都是用auto来修饰的,所以在程序中很少见到. 2.static 它作用可大了,除了可以修饰变量,还可以修饰函数,修饰变量,改变其作用域和生命周期,修 ...

  7. Ubuntu下安装Numpy, SciPy and Matplotlib

    Python开发环境包含科学计算,需要安装NumPy, SciPy, Matplotlib.其中Matplotlib依赖于Python和NumPy.我们先安装NumPY和SciPy.  Matplot ...

  8. 基于Java Netty框架构建高性能的部标808协议的GPS服务器

    使用Java语言开发一个高质量和高性能的jt808 协议的GPS通信服务器,并不是一件简单容易的事情,开发出来一段程序和能够承受数十万台车载接入是两码事,除去开发部标808协议的固有复杂性和几个月长周 ...

  9. c#项目架构搭建经验

    读过.Net项目中感觉代码写的不错(备注1)有:bbsMax(可惜唧唧喳喳鸟像消失了一样),Umbraco(国外开源的cms项目),Kooboo(国内做开源cms).本人狭隘,读的代码不多,范围也不广 ...

  10. C# 利用ICSharpCode.SharpZipLib实现在线加密压缩和解密解压缩

    这里我们选用ICSharpCode.SharpZipLib这个类库来实现我们的需求. 下载地址:http://icsharpcode.github.io/SharpZipLib/ 1.单个或多个文件加 ...