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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章