Storm常用API

API简介

Component组件

1)基本接口

       (1)IComponent接口

       (2)ISpout接口

       3IRichSpout接口

       (4)IStateSpout接口

       (5)IRichStateSpout接口

       (6)IBolt接口

       7IRichBolt接口

       (8)IBasicBolt接口

2)基本抽象类

       (1)BaseComponent抽象类

       2BaseRichSpout抽象类

       3BaseRichBolt抽象类

(4)BaseTransactionalBolt抽象类

       (5)BaseBasicBolt抽象类

 spout水龙头

Spout的最顶层抽象是ISpout接口

(1)Open()

是初始化方法

(2)close()

在该spout关闭前执行,但是并不能得到保证其一定被执行,kill -9时不执行,Storm kill {topoName} 时执行

(3)activate()

       当Spout已经从失效模式中激活时被调用。该Spout的nextTuple()方法很快就会被调用。

(4)deactivate ()

       当Spout已经失效时被调用。在Spout失效期间,nextTuple不会被调用。Spout将来可能会也可能不会被重新激活。

(5)nextTuple()

       当调用nextTuple()方法时,Storm要求Spout发射元组到输出收集器(OutputCollecctor)。NextTuple方法应该是非阻塞的,所以,如果Spout没有元组可以发射,该方法应该返回。nextTuple()、ack()和fail()方法都在Spout任务的单一线程内紧密循环被调用。当没有元组可以发射时,可以让nextTuple去sleep很短的时间,例如1毫秒,这样就不会浪费太多的CPU资源。

(6)ack()

成功处理tuple回调方法

(7)fail()

处理失败tuple回调方法

原则:通常情况下(Shell和事务型的除外),实现一个Spout,可以直接实现接口IRichSpout,如果不想写多余的代码,可以直接继承BaseRichSpout

bolt转接头

bolt的最顶层抽象是IBolt接口

(1)prepare()

       prepare ()方法在集群的工作进程内被初始化时被调用,提供了Bolt执行所需要的环境。

(2)execute()

接受一个tuple进行处理,也可emit数据到下一级组件。

(3)cleanup()

       Cleanup方法当一个IBolt即将关闭时被调用。不能保证cleanup()方法一定会被调用,因为Supervisor可以对集群的工作进程使用kill -9命令强制杀死进程命令。

       如果在本地模式下运行Storm,当拓扑被杀死的时候,可以保证cleanup()方法一定会被调用。

实现一个Bolt,可以实现IRichBolt接口或继承BaseRichBolt,如果不想自己处理结果反馈,可以实现 IBasicBolt接口或继承BaseBasicBolt,它实际上相当于自动做了prepare方法和collector.emit.ack(inputTuple)。

spout的tail特性

Storm可以实时监测文件数据,当文件数据变化时,Storm自动读取。

以下是实时单词统计案例,参考其中使用的api

采用maven构建项目

pom文件如下:

<dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.storm/storm-core -->
        <dependency>
            <groupId>org.apache.storm</groupId>
            <artifactId>storm-core</artifactId>
            <version>${storm.version}</version>
        </dependency>
    </dependencies>

1)需求

       实时统计发射到Storm框架中单词的总数。

2)分析

设计一个topology,来实现对文档里面的单词出现的频率进行统计。

整个topology分为三个部分:

(1)WordCountSpout:数据源,在已知的英文句子中,随机发送一条句子出去。

(2)WordCountSplitBolt:负责将单行文本记录(句子)切分成单词

(3)WordCountBolt:负责对单词的频率进行累加

3)代码

(1)创建spout

import java.util.Map;
import org.apache.storm.spout.SpoutOutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichSpout;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Values;

public class WordCountSpout extends BaseRichSpout {
	
	private static final long serialVersionUID = 1L;
	private SpoutOutputCollector collector;

	@Override
	public void nextTuple() {
		// 1 发射模拟数据
		collector.emit(new Values("i am ximen love jinlian"));
		
		// 2 睡眠2秒
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void open(Map arg0, TopologyContext arg1, SpoutOutputCollector collector) {
		this.collector = collector;
	}

	@Override
	public void declareOutputFields(OutputFieldsDeclarer declarer) {
		declarer.declare(new Fields("love"));
	}
}

(2)创建切割单词的bolt

import java.util.Map;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Fields;
import org.apache.storm.tuple.Tuple;
import org.apache.storm.tuple.Values;

public class WordCountSplitBolt extends BaseRichBolt {

	private static final long serialVersionUID = 1L;
	private OutputCollector collector;

	@Override
	public void execute(Tuple input) {
		// 1 获取传递过来的一行数据
		String line = input.getString(0);
		// 2 截取
		String[] arrWords = line.split(" ");
		
		// 3 发射
		for (String word : arrWords) {
			collector.emit(new Values(word, 1));
		}
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void prepare(Map arg0, TopologyContext arg1, OutputCollector collector) {
		this.collector = collector;
	}

	@Override
	public void declareOutputFields(OutputFieldsDeclarer declarer) {
		declarer.declare(new Fields("word", "num"));
	}
}

(3)创建汇总单词个数的bolt

import java.util.HashMap;
import java.util.Map;
import org.apache.storm.task.OutputCollector;
import org.apache.storm.task.TopologyContext;
import org.apache.storm.topology.OutputFieldsDeclarer;
import org.apache.storm.topology.base.BaseRichBolt;
import org.apache.storm.tuple.Tuple;

public class WordCountBolt extends BaseRichBolt {

	private static final long serialVersionUID = 1L;
	private Map<String, Integer> map = new HashMap<String, Integer>();

	@Override
	public void execute(Tuple input) {

		// 1 获取传递过来的数据
		String word = input.getString(0);
		Integer num = input.getInteger(1);

		// 2 累加单词
		if (map.containsKey(word)) {
			Integer count = map.get(word);
			map.put(word, count + num);
		} else {
			map.put(word, num);
		}

System.err.println(Thread.currentThread().getId() + "  word:" + word + "  num:" + map.get(word));
	}

	@SuppressWarnings("rawtypes")
	@Override
	public void prepare(Map arg0, TopologyContext arg1, OutputCollector collector) {

	}

	@Override
	public void declareOutputFields(OutputFieldsDeclarer arg0) {
		// 不输出
	}
}

(4)创建程序的拓扑main

import org.apache.storm.Config;
import org.apache.storm.LocalCluster;
import org.apache.storm.StormSubmitter;
import org.apache.storm.topology.TopologyBuilder;
import org.apache.storm.tuple.Fields;

public class WordCountMain {

	public static void main(String[] args) {
		// 1、准备一个TopologyBuilder
		TopologyBuilder builder = new TopologyBuilder();

		builder.setSpout("WordCountSpout", new WordCountSpout(), 1);
		builder.setBolt("WordCountSplitBolt", new WordCountSplitBolt(), 2).shuffleGrouping("WordCountSpout");
		builder.setBolt("WordCountBolt", new WordCountBolt(), 4).fieldsGrouping("WordCountSplitBolt", new Fields("word"));

		// 2、创建一个configuration,用来指定当前topology 需要的worker的数量
		Config conf = new Config();
		conf.setNumWorkers(2);

		// 3、提交任务 -----两种模式 本地模式和集群模式
		if (args.length > 0) {
			try {
				// 4 分布式提交
				StormSubmitter.submitTopology(args[0], conf, builder.createTopology());
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			// 5 本地模式提交
			LocalCluster localCluster = new LocalCluster();
			localCluster.submitTopology("wordcounttopology", conf, builder.createTopology());
		}
	}
}

(5)测试

发现132线程只处理单词am和单词love;169进程处理单词i、ximen、jianlian。这就是分组的好处。

132  word:am  num:1
132  word:love  num:1
169  word:i  num:1
169  word:ximen  num:1
169  word:jinlian  num:1
发布了91 篇原创文章 · 获赞 26 · 访问量 15万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览