一、簡介
Apache Storm 是一個開源的分佈式、實時、可擴展、容錯的計算系統。Apache Storm Storm可以很容易做到可靠地處理無限的數據流,像Hadoop批量處理大數據一樣。Storm處理速度很快,每個節點每秒鐘可以處理超過百萬的數據組。
Apache Storm應用的場景例如:實時分析、在線機器學習、連續計算、分佈式RPC、ETL 等。
官方圖片
如圖所示,水源源不斷的從水龍頭流出來,可以流到到不同的池子,然後最後匯合到一個池子 ,形象的描述了Storm可以處理無限的數據流,經過每個節點,可以對數據進行過濾、計算等操作,然後在發送到下一個節點進行處理。
二、Storm架構
Apache Storm分佈式集羣主要節點由控制節點(Nimbus節點)和工作節點(Supervisor節點),控制節點可以一個,工作節點多個組成的,而Zookeeper主要負責Nimbus節點和Supervisor節點之間的協調工作。
Nimbus節點負責資源分配和任務分配,通過Zookeeper監控Supervisor狀態,Supervisor節點定期接受Nimbus節點分配任務,並會從Nimbus下載代碼,並啓動對應的worker進程並監控worker 狀態,每一worker是一個獨立的JVM進程,Worker中運行Spout/Bolt線程Task任務,Storm使用zookeeper來協調整個集羣,狀態信息(Nimbus分發的任務、Supervisor、worker的心跳等)都保存在Zookeeper上。
三、分佈式實時計算應用結構
Apache Storm 是一個開源的分佈式、實時計算應用,實時計算應用它是由Topologys、Streams、Spouts、Bolts、Stream groupings等元素組成的。
1、Topologys(拓撲)
Storm的Topologies是一個分佈式實時計算應用,它通過Stream groupings把spouts和Bolts串聯起來組成了流數據處理結構,Topologies在集羣中一直運行,直到kill(storm kill topology-name [-w wait-time-secs]) 拓撲時撲纔會結束運行。
運行一個拓撲只要把代碼打包成一個jar,然後在storm集羣環境下,執行命令
storm jar topology-jar-path class........
拓撲運行模式:本地模式和分佈式模式。
本地模式:
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("word-count", conf, builder.createTopology());
分佈式模式:
conf.setNumWorkers(2);
StormSubmitter.submitTopology(args[0], conf, builder.createTopology());
2、Streams(數據流)
Streams是storm最核心的抽象概念,一個Stream是一個沒有邊界的tuple序列,Streams是由Tuple(元組)組成的,Tuple支持的類型有Integer、 Long、 Short、Byte、String、Double、Float、Boolean、Byte arrays。Tuple也支持可序列化的對象。
Tuple是數據流中的一個基本處理單元,包含了多個Field和對應的值,可以理解爲key-value的map,因爲Bolt中通過declareOutputFields事先定義好往下傳的字段名稱,所以在構造Tuple時,只要傳入對應的value(value List)。
1)declareOutputFields事先定義好往下傳的字段名稱
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
//定義了傳到下一個bolt的字段描述
declarer.declare(new Fields("field"));
}
2)然後通過emit要填充value
collector.emit(new Values(value))
說明:
1)數據流都有默認的id(streamId=default)
public List<Integer> emit(List<Object> tuple) {
return emit(Utils.DEFAULT_STREAM_ID, tuple);
}
---源代碼2)我們可以自己定義數據流Id,declareOutputFields事先定義好往下傳的字段名稱時,可以聲明對應的數據流ID: declarer.declareStream("streamId", new Fields("field"))
3、Spouts(數據源)
Spout是拓撲的數據流的源頭,Spout不斷的從外部讀取數據(數據庫、kafka等外部資源),併發送到拓撲中進行實時的處理。
Spout是主動模式,Spout繼承BaseRichSpout或者IRichSpout類不斷的調用nextTuple()函數,然後通過emit發送數據流。
參數說明:
Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS:一個Tuple元組全部完成的最大等待時間,默認是30秒;
Config.TOPOLOGY_MAX_SPOUT_PENDING:設置一次等候單個spout任務的元組最大的數量,(等候意味着這元組沒有被acked或失敗),設置這個值可以防止隊列溢出
4、Bolts(數據流處理組件)
Bolt接收Spout或者上游的Bolt發來的Tuple(數據流),然後對數據流進行處理(數據的過濾、統計等等的操作)。
Bolt是被動模式,Bolt繼承BaseBasicBolt類或者IRichBolt 接口等來實現,當 Bolt接收Spout或者上游的Bolt發來的Tuple(數據流)時調用execute 方法,並對數據流進行處理完,OutputCollector的emit 發送數據流,execute 方法在Bolt中負責接收數據流和發送數據流。
5、Stream groupings(數據流分組)
Storm是通過Stream groupings把spouts和Bolts串聯起來組成了流數據處理結構 。
Storm對Stream groupings定義了8種數據流分組方式:
1)Shuffle grouping(隨機分組):對Tuple(數據流)隨機的分發到下一個bolt的Tasks(任務),每個任務同等機會獲取Tupe,保證了集羣的負載均衡。
2)Fields grouping(字段分組):對指定的字段對數據流進行分組,相同的字段對應的數據流都會交給同個bolt中Task來處理,不同的字段的數據流會分發到不同的Task來處理。
3)Partial Key grouping(部分字段分組):按字段進行分組,這種跟Fields grouping很相似,但這種方式會考慮下游 Bolt 數據處理的均衡性問題,會提供更好的資源利用,可以參考官方的解釋。
4)All grouping(完全分組): Tuple(數據流)會被同時的發送到下一個bolt中的所有Task(任務)。
5)Global grouping(全局分組):Tuple(數據流)會被髮送到 Bolt 的同一個Id 最小的Task(任務)。
6)None grouping(無分組):使用這種方式說明你不關心數據流如何分組。目前這種方式的結果與隨機分組完全等效,不過未來可能會考慮通過非分組方式來讓 Bolt 和它所訂閱的 Spout 或 Bolt 在同一個線程中執行。
7)Direct grouping(直接分組):通過OutputCollector emitDirect 方法指定下一個bolt的具體Task來處理。
8)Local or shuffle grouping(本地或隨機分組):如果目標 Bolt 有一個或更多的任務在相同的Worker進程中,Tuple就發送給這些Task,否則Tuple會被隨機分發(跟Shuffle grouping一樣)。
6、Reliability(可靠性)
Storm 爲了保證spout發送的tuple能夠成功的處理,通過 tuple 樹跟蹤每個Tuple是否被成功的處理。Storm有配置一個Tuple元組全部完成的最大等待時間,如果超過這個時間,就默認這個Tuple失敗,重新發送Tuple。通過這種機制保證了Tuple的可靠性。可以參考官方文檔對數據處理說明
Config.TOPOLOGY_MESSAGE_TIMEOUT_SECS:一個Tuple元組全部完成的最大等待時間,默認是30秒。
7、Tasks(任務)
Task是對應一個spoout或者bolt實例,在Storm集羣中每個spoout或者bolt對應多個Task來執行,spoout或者bolt設置多個並行度(setSpout/setBolt),就有對應的多個個Task,spoout的nextTuple()/bolt 的execute() 會被執行。
8、Workers(工作進程)
拓撲運行在一個或者多個worker上,每一worker是一個獨立的JVM進程,進程裏面包含一個或者多個executor(線程),一個線程會處理一個或者多個Task(任務)。
Config.TOPOLOGY_WORKERS設置worker數量。