一、Storm簡介
Storm是Twitter開源的一個類似於Hadoop的實時數據處理框架。
Storm能實現高頻數據和大規模數據的實時處理。
官網資料顯示storm的一個節點在1秒鐘能夠處理100萬個100字節的消息([email protected]的CPU,24GB的內存)
(storm +kafka+flume)
二、HADOOP與STORM比較
數據來源:HADOOP處理的是HDFS上TB級別的數據(歷史數據),STORM是處理的是實時新增的某一筆數據(實時數據);
處理過程:HADOOP是分MAP階段和REDUCE階段,STORM是由用戶定義處理流程,流程中可以包含多個步驟,每個步驟可以是數據源(SPOUT)或處理邏輯(BOLT);
是否結束:HADOOP最後是要結束的,STORM是沒有結束狀態,到最後一步時,就停在那,直到有新數據進入時再從頭開始;
處理速度:HADOOP是以處理HDFS上大量數據爲目的,處理速度慢,STORM是隻要處理新增的某一筆數據即可,可以做到很快;
適用場景:HADOOP是在要處理批量數據時用的,不講究時效性,STORM是要處理某一新增數據時用的,要講時效性;
package storm;
import java.util.Map;
import backtype.storm.Config;
import backtype.storm.LocalCluster;
import backtype.storm.spout.SpoutOutputCollector;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.topology.TopologyBuilder;
import backtype.storm.topology.base.BaseRichBolt;
import backtype.storm.topology.base.BaseRichSpout;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
/**
* 數據累加的操作,spout產生數據(在這裏自己產生),bolt對數據累加求和
* @author Administrator
*
*/
public class LocalStormTopology {//都在一個類裏面實現,需要寫一個靜態name類
public static class DataSourceSpout extends BaseRichSpout{//spout繼承BaseRichSpout類,它有3個未實現的方法
private Map conf;//第一個未實現的方法。不知道會不會用上,先保存
private TopologyContext context;
private SpoutOutputCollector collector;
/**
* 本實例運行的是被調用一次,只能執行一次。
*/
public void open(Map conf, TopologyContext context,
SpoutOutputCollector collector) {//第一個未實現的方法,本實例運行時被調用一次,Map conf配置參數,可以獲取topology的配置信息,TopologyContext理解爲Topology的上下文,collector,發射器,將spout產生的數據發射出去
this.conf = conf;
this.context = context;
this.collector = collector;
}
/**
* 死循環的調用,心跳
*/
int i=0;
public void nextTuple() {//第二個未實現的方法,程序運行過程中不斷被調用,調用此方法會不斷產生數據
System.out.println("spout:"+i);//打印每次產生的數據
this.collector.emit(new Values(i++));//將產生的數據發射出去,發射需要emit這個方法,接受的是tuple,是list類型,tuple裏面放的是列表的數據,裏面是封裝了列表;storm裏面封裝了一個values類,new Values相當於一個tuple,直接將i傳進去,點進去,他繼承了ArrayList,相當於創建了一個list,往list裏面添加一個元素,每次都會發送數據,所以i++,每次遞增加一
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* declarer方法的意思是聲明輸出的內容
*/
public void declareOutputFields(OutputFieldsDeclarer declarer) {//第三個未實現的方法,spout只管發射數據,不指定目標,需要指定發射數據的的名稱,bolt讀取有標示的數據
declarer.declare(new Fields("num"));//declare方法接受參數fields,就new一個Fields,Fileds可接受一個可變參數(3個點)或者傳一個list列表,需要指定一個字段名稱,自定義爲num。前面tuple封裝了一個數據,這裏對應也是一個字段,如果前面發射兩個參數(i++,i+2),這裏就指定2個字段('num''num'),bolt可通過num(num2)字段獲取i++數據(i+2)。spout發射的數據與字段num做了關聯
}
}
//寫一個靜態name類,也要實現3個未實現的方法
public static class Sumbolt extends BaseRichBolt{
private Map stormConf;
private TopologyContext context;
private OutputCollector collector;
public void prepare(Map stormConf, TopologyContext context,
OutputCollector collector) {//第一個未實現的方法
this.stormConf = stormConf;
this.context = context;
this.collector = collector;//只會用到這個
}
int sum = 0;
public void execute(Tuple input) {//這個方法,bolt也有個死循環,不斷讀取數據,每次獲取的也是一個Tuple
//input.getInteger(0);//通過get方法Integer傳遞的是參數,獲取的數據是列表的腳標,獲取的是list的元素,不建議使用這種方式。
Integer value = input.getIntegerByField("num");//因爲之前已經指定了num字段,所以通過num字段獲取i++的值,使用declare方法指定的字段
sum+=value;//因爲bolt需要對獲取的字段的值累加求和
System.out.println("sum:"+sum);//直接將sum打印出來,打印每次累加求和的結果
//this.collector.emit(tuple);
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//因爲這個bolt已經是最後一個bolt,bolt不需要往外發射數據,這裏不需要定義字段
}
}
//需要topology。main函數將spout和bolt組裝在一起
public static void main(String[] args) {
TopologyBuilder topologyBuilder = new TopologyBuilder();//先new TopologyBuilder,
topologyBuilder.setSpout("spout_id", new DataSourceSpout());//首先設置spout,id簡單自定義爲spout_id,後面需要具體指定spout類
topologyBuilder.setBolt("bolt_id", new Sumbolt()).shuffleGrouping("spout_id");//需要將spout和bolt連接起來,bolt接spout,在bolt調用一個方法shuffleGrouping(指定'spout_id')
LocalCluster localCluster = new LocalCluster();//組裝後需要運行,在本地運行,造一個本地的軌道
localCluster.submitTopology("topology", new Config(), topologyBuilder.createTopology());//第一個是topology的名稱,第二個是配置參數是map結構,storm提供了一個配置類,new Config(點進去,繼承了HashMap),後面需要一個storm Topology,我們指定爲topologyBuilder.createTopology()
}
}