1. Storm编程模型概要

消息源spout, 继承BaseRichSpout类 或 实现IRichSpout接口
1)BaseRichSpout类相对比较简单,需要覆写的方法较少,满足基本业务需求
2)IRichSpout接口,需要实现较多的框架定义好的抽象方法,部分方法和BaseRichSpout重叠,通常用于比较复杂的业务数据接入需求

重要方法
open方法: 初始化动作(传入参数,传入上下文),是spout第一个执行的方法,主类中的拓扑配置实例conf会将相关参数作为实参传入给open
nextTuple方法: 数据接入,消息tuple发射 (spout中最重要的方法)
ack方法:传入参数是object,本质是id,标识唯一一个tuple, 实现该tuple被spout成功处理后的逻辑,storm消息保证的API接口
fail方法:与ack方法对应,实现tuple处理失败后的逻辑, storm消息保证的API接口
declareOutputFields方法:声明输出字段,storm中的每个tuple都要求设置输出字段

处理单元bolt: 继承BaseBasicBolt类,或者实现IRichBolt接口

重要方法
*prepare方法:worker初始化,传递参数,声明上下文
*execute方法:接收1个tuple, 实现bolt处理逻辑,发射新tuple(最重要)
*clearup方法:worker关闭前调用,资源释放等,但不能保证该方法一定会被调用(worker进程出现问题等情况)
*declareOutputFields方法:声明输出tuple的每个字段,storm中的每个tuple都要求设置输出字段

2. wordcount代码架构

从拓扑的角度来看各个类间的关系

各个类主要功能

1. spout中随机发送内置的语句作为消息源
2. 第一组bolt进行语句切分,分离出单词,然后发送给下游bolt
3. 第二组bolt,基于字段分组策略,订阅(接收)切分好的单词,完成单词统计并将结果发送给下游
4. 最后1个bolt, 将结果打印到console

3. RandomSentenceSpout

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;
import java.util.Map;
import java.util.Random;
/**
*
* @Author: shayzhang
* @Email: shayzhang@sina.com
* @Blog: cn.blogs.com/shay-zhangjin
* @Describe: select 1 random sentence and send to next-level bolt using field streaming groups
*
*/
public class RandomSentenceSpout extends BaseRichSpout {
SpoutOutputCollector spcollector; //for emit tuple
Random random; //spout initialize, spout执行的第一个方法,主要是从conf自动传入spout发送数据的SpoutOutputCollector
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
spcollector = spoutOutputCollector;
random = new Random();
}
//generate tuple and emit
public void nextTuple() {
//每2秒发送一次tuple
Utils.sleep(2000);
String[] sentences = new String[]{
"And if the golden sun",
"four score and seven years ago",
"storm hadoop hbase spark",
"storm is a real-time processing frame-work",
"you make my night bright"
};
// select random sentence
String msg = sentences[random.nextInt(sentences.length)];
// emit tuple, doesn't assign message id
spcollector.emit(new Values(msg.trim().toLowerCase()) );
// ack tuple, successfully sent
} //每个tuple都要说明字段
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("sentence") );
}
}

4. WordNormalizserBolt

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import java.util.Map; /**
*
* @author: shayzhang
* @email: shayzhang@sina.com
* @blog: cn.blogs.com/shay-zhangjin
* @description: split sentence into words and emit
*
*/
public class WordNormalizerBolt implements IRichBolt {
private OutputCollector wncollector; //bolt执行的第一个方法,主类中conf对象,将相关数据推送过来,重点是获取Bolt发送数据使用的OutputCollector
public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
wncollector = outputCollector;
} public void execute(Tuple tuple) {
//获取整个句子
String sentence = tuple.getString(0);
//分离出单词
String words[] = sentence.split(" ");
//发送每个单词
for(String word: words){
wncollector.emit(new Values(word));
wncollector.ack(tuple);

}
}
  //Bolt退出会执行,但不能保证cleanup方法一定会被执行到(节点故障等)
public void cleanup() { }
//字段说明
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("word")); //当下游bolt通过fieldsGrouping方式获取数据时尤为重要,要保障上下游使用的Fields能够对的上
} public Map<String, Object> getComponentConfiguration() {
return null;
}
}

5. WordCountBolt

import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
import java.util.HashMap;
import java.util.Map; /**
*
* @author: shayzhang
* @email: shayzhang@sina.com
* @blog: cn.blogs.com/shay-zhangjin
* @description: count word number, emit top N
*
*/
public class WordCountBolt implements IRichBolt{
OutputCollector collector; //for emit
Map<String,Integer> counters; //for word count //init bolt, bolt执行的第一个方法,主类中的config对象自动进行参数传递
public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
collector = outputCollector;
counters = new HashMap<String, Integer>(); } //统计每个单词的次数,并排序
public void execute(Tuple tuple) {
String word = tuple.getString(0); //处理收到的每一个word
if ( !counters.containsKey(word)){
counters.put(word,1);
}else{
counters.put(word, counters.get(word)+1);
} //实时输出 <word, count>
Integer length = counters.keySet().size();
Integer count = 0; for(String key:counters.keySet()){
word = "[" + new String(key) + ": " + String.valueOf(counters.get(key)) + "]";
collector.emit(new Values(word));
collector.ack(tuple);
count++;
if(count==length){
break;
} }//execute }//execute public void cleanup() { } public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("wordcount"));
} public Map<String, Object> getComponentConfiguration() {
return null;
}
}

6. PrintBolt

import backtype.storm.task.OutputCollector;
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.Fields;
import backtype.storm.tuple.Tuple;
import java.util.Map; public class PrintBolt extends BaseBasicBolt{ OutputCollector collector; public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
collector = outputCollector;
} public void execute(Tuple tuple, BasicOutputCollector basicOutputCollector) {
try {
String msg = tuple.getString(0);
if (msg != null) {
System.out.println(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
} public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
outputFieldsDeclarer.declare(new Fields("result"));
}
}

7. 主类:构建拓扑,根据是否传入参数决定运行本地模式、集群模式

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.topology.TopologyBuilder;
import backtype.storm.tuple.Fields;
import backtype.storm.utils.Utils; public class WordCountTopology { public static void main(String args[]) throws AlreadyAliveException, InvalidTopologyException {
//Topology配置
Config config = new Config(); //Topology构造器
TopologyBuilder builder = new TopologyBuilder(); //使用builder构建Topology
//spout, 2个executor
builder.setSpout("RandomSentence", new RandomSentenceSpout(), 2); //bolt, 2个executor, 从id为RandomSentence的spout接收tuple, shuffle方式
builder.setBolt("WordNormalizer", new WordNormalizerBolt(), 2).shuffleGrouping("RandomSentence"); //从id为“RandomSentence”的spout获取数据 //bolt, 2个executor,从id为wordNormalizer的bolt接收tuple, fields方式: 根据‘word’字段, 进行单词接收
builder.setBolt("wordcount", new WordCountBolt(), 2).fieldsGrouping("WordNormalizer", new Fields("word")); //从id为WordNormalizser的bolt获取数据,并且按照word域进行分发 //bolt, 1个executor, 收集所有结果并打印, global方式接收所有id为wordcount的bolt发出的信息
builder.setBolt("print", new PrintBolt(), 1).shuffleGrouping("wordcount"); //从id为wordcount的bolt获取数据 //设置debug, true则打印节点间交换的所有信息
config.setDebug(false); //通过是否有参数,来控制启动本地模式,集群模式
if(args!=null && args.length>0){
//有提交参数,执行集群模式
config.setNumWorkers(1); //1个worker进程
try {
//提交拓扑到storm集群, 拓扑名通过提交参数给定(args[0])
StormSubmitter.submitTopology(args[0], config, builder.createTopology());
} catch (AlreadyAliveException e) {
e.printStackTrace();
} catch (InvalidTopologyException e) {
e.printStackTrace();
}
}else{
//无提交参数,执行本地模式,调测用
//本地模式,通过LocalCluster实例提交拓扑任务
config.setMaxTaskParallelism(1);
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("WC_Local", config, builder.createTopology()); //运行5分钟后,kill该topology任务
Utils.sleep(300000);
cluster.killTopology("WC_Local");
cluster.shutdown(); } }//main
}//WordCountTopology

8. 本地模式运行

在IDEA中选择主类,直接运行即可, 从IDE终端可以看到代码是否正常运行

03_Storm编程上手-wordcount的更多相关文章

  1. 第三次作业-结对编程(wordcount)

    GIT地址 https://github.com/gentlemanzq/WordCount.git GIT用户名  gentlemanzq 结对伙伴博客地址 https://home.cnblogs ...

  2. MapReduce 编程模型 & WordCount 示例

    学习大数据接触到的第一个编程思想 MapReduce.   前言 之前在学习大数据的时候,很多东西很零散的做了一些笔记,但是都没有好好去整理它们,这篇文章也是对之前的笔记的整理,或者叫输出吧.一来是加 ...

  3. 04_Storm编程上手_WordCount集群模式运行

    1. 要解决的问题:代码打包 前一篇的代码,在IDEA中通过maven工程创建,通过IDEA完成代码打包 1)File -> Project Structure  2) 选择Artifacts, ...

  4. Spark编程环境搭建及WordCount实例

    基于Intellij IDEA搭建Spark开发环境搭建 基于Intellij IDEA搭建Spark开发环境搭——参考文档 ● 参考文档http://spark.apache.org/docs/la ...

  5. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  6. 【Visual C++】游戏编程学习笔记之一:五毛钱特效之透明和半透明处理

    本系列文章由@二货梦想家张程 所写,转载请注明出处. 本文章链接:http://blog.csdn.net/terence1212/article/details/44163799 作者:ZeeCod ...

  7. 实训任务04 MapReduce编程入门

    实训任务04 MapReduce编程入门 1.实训1:画图mapReduce处理过程 使用有短句“A friend in need is a friend in deed”,画出使用MapReduce ...

  8. 2.4 Scala函数式编程

    一.函数定义与使用 1.函数的定义 2.匿名函数 举例: Scala自动推断变量类型,不用声明: 一个下划线只能表示这一个参数的一次出现 二.高阶函数 定义:函数定义的括号里仍然是个函数的函数,叫作高 ...

  9. Hive实现WordCount详解

    一.WordCount原理 初学MapReduce编程,WordCount作为入门经典,类似于初学编程时的Hello World.WordCount的逻辑就是给定一个/多个文本,统计出文本中每次单词/ ...

随机推荐

  1. RESTful HTTP的实践(转)

    add by zhj: 文章有点老了,2009年的,到现在已经六年了,不过还是很有参考价值的. 另外,吐槽一下PUT method,竟然允许用户用实例号来创建,靠,这也行,实例号还是后台来定义比较方便 ...

  2. Navicat工具、pymysql模块、数据备份

    IDE工具介绍(Navicat) 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具,我们使用Navicat工具,这个工具本质上就是一个socket客户端,可视化的连接mys ...

  3. 注册表REG文件编写大全

    Windows 中的注册表文件( system.dat 和 user.dat )是 Windows 的核心数据库,因此,对 Windows 来说是非常重要的. 通过修改注册表文件中的数据,可以达到优化 ...

  4. 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景

    开言: 在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果.所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕. 为了大家做游戏方便,于是我给这个引擎加了这么 ...

  5. R语言之多重共线性的判别以及解决方法

    多重共线性(Multicollinearity)是指线性回归模型中的解释变量之间由于存在精确相关关系或高度相关关系而使模型估计失真或难以估计准确.   1.可以计算X矩阵的秩qr(X)$rank,如果 ...

  6. MongoDB简单CRUD场景

    MongoDB简单CRUD命令操作 (1)新建数据库:use 数据库名 (2)显示所有数据库:show dbs; (3)新建集合(两种方式)  隐式创建:在创建集合的同时往集合里面添加数据---db. ...

  7. 20165324 学习基础与C语言学习心得

    20165324 技能学习心得与C语言学习 一.读后感及技能学习 做中学读后感 我认为给学生具体的, 能实践的, 能马上看到因果关系的教材和练习, 是激发学生兴趣, 好奇心, 求知欲的好方法. 我就是 ...

  8. Mac下 Visual VM 无法检测到本地的Java进程

    我下载的是VisualVM1.4 下载完成之后,在左边栏Local哪里只有VisualVM自己的进程. 我本地启动的eclipse和intelliJ都没有检测到. 网上查阅后都是Window下的解决方 ...

  9. BFC 详说 Block Formatting Contexts (块级格式化上下文)

    定位方案是控制元素的布局,在 CSS 2.1 中,有三种定位方案——普通流 (Normal Flow) .浮动 (Floats) 和绝对定位 (Absolute Positioning) ,下面分别对 ...

  10. 48. Rotate Image(旋转矩阵)

      You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise) ...