一、Storm簡介
Storm是一個免費并開源的分布式實時計算系統(tǒng)牙勘。利用Storm可以很容易做到可靠地處理無限的數(shù)據(jù)流职恳,像Hadoop批量處理大數(shù)據(jù)一樣,Storm可以實時處理數(shù)據(jù)谜悟。
Storm 很簡單话肖,可用于任意編程語言北秽。Apache Storm 采用 Clojure 開發(fā)葡幸。Storm 有很多應(yīng)用場景,包括實時數(shù)據(jù)分析贺氓、聯(lián)機學(xué)習(xí)蔚叨、持續(xù)計算、分布式 RPC辙培、ETL 等蔑水。
Hadoop(大數(shù)據(jù)分析領(lǐng)域無可爭辯的王者)專注于批處理?這種模型對許多情形(比如為網(wǎng)頁建立索引)已經(jīng)足夠,但還存在其他一些使用模型,它們需要來自高度動態(tài)的來源的實時信息?為了解決這個問題,就得借助 Nathan Marz 推出的 storm(現(xiàn)在已經(jīng)被Apache孵化)storm 不處理靜態(tài)數(shù)據(jù),但它處理連續(xù)的流數(shù)據(jù)。
storm特點:
- 編程簡單:開發(fā)人員只需要關(guān)注應(yīng)用邏輯扬蕊,而且跟Hadoop類似搀别,Storm提供的編程原語也很簡單
- 高性能,低延遲:可以應(yīng)用于廣告搜索引擎這種要求對廣告主的操作進行實時響應(yīng)的場景尾抑。
- 分布式:可以輕松應(yīng)對數(shù)據(jù)量大歇父,單機搞不定的場景
- 可擴展: 隨著業(yè)務(wù)發(fā)展,數(shù)據(jù)量和計算量越來越大再愈,系統(tǒng)可水平擴展
- 容錯:單個節(jié)點掛了不影響應(yīng)用
- 消息不丟失:保證消息處理
storm與hadoop的比較:
1.Storm用于實時計算榜苫,Hadoop用于離線計算。
2. Storm處理的數(shù)據(jù)保存在內(nèi)存中翎冲,源源不斷垂睬;Hadoop處理的數(shù)據(jù)保存在文件系統(tǒng)中,一批一批。
Storm的數(shù)據(jù)通過網(wǎng)絡(luò)傳輸進來驹饺;Hadoop的數(shù)據(jù)保存在磁盤中钳枕。
Storm與Hadoop的編程模型相似
結(jié)構(gòu) | Hadoop | Storm |
---|---|---|
主節(jié)點 | JobTracker | Nimbus |
從節(jié)點 | TaskTracker | Supervisor |
應(yīng)用程序 | Job | Topology |
工作進程名稱 | Child | Worker |
計算模型 | Map / Reduce | Spout / Bolt |
二、Storm集群架構(gòu)
Storm集群采用主從架構(gòu)方式赏壹,主節(jié)點是Nimbus么伯,從節(jié)點是Supervisor,有關(guān)調(diào)度相關(guān)的信息存儲到ZooKeeper集群中卡儒,架構(gòu)如下圖所示:
Nimbus
Storm集群的Master節(jié)點田柔,負(fù)責(zé)分發(fā)用戶代碼,指派給具體的Supervisor節(jié)點上的Worker節(jié)點骨望,去運行Topology對應(yīng)的組件(Spout/Bolt)的Task硬爆。
Supervisor
Storm集群的從節(jié)點,負(fù)責(zé)管理運行在Supervisor節(jié)點上的每一個Worker進程的啟動和終止擎鸠。通過Storm的配置文件中的supervisor.slots.ports配置項缀磕,可以指定在一個Supervisor上最大允許多少個Slot,每個Slot通過端口號來唯一標(biāo)識劣光,一個端口號對應(yīng)一個Worker進程(如果該Worker進程被啟動)袜蚕。
Worker
運行具體處理組件邏輯的進程。Worker運行的任務(wù)類型只有兩種绢涡,一種是Spout任務(wù)牲剃,一種是Bolt任務(wù)。
Task
worker中每一個spout/bolt的線程稱為一個task. 在storm0.8之后雄可,task不再與物理線程對應(yīng)凿傅,不同spout/bolt的task可能會共享一個物理線程,該線程稱為executor数苫。
ZooKeeper
用來協(xié)調(diào)Nimbus和Supervisor聪舒,如果Supervisor因故障出現(xiàn)問題而無法運行Topology,Nimbus會第一時間感知到虐急,并重新分配Topology到其它可用的Supervisor上運行
三箱残、Storm編程模型
Strom在運行中可分為spout與bolt兩個組件,其中止吁,數(shù)據(jù)源從spout開始被辑,數(shù)據(jù)以tuple的方式發(fā)送到bolt,多個bolt可以串連起來赏殃,一個bolt也可以接入多個spot/bolt.運行時原理如下圖:
Topology:Storm中運行的一個實時應(yīng)用程序的名稱敷待。將 Spout、 Bolt整合起來的拓?fù)鋱D仁热。定義了 Spout和 Bolt的結(jié)合關(guān)系榜揖、并發(fā)數(shù)量勾哩、配置等等。
Spout:在一個topology中獲取源數(shù)據(jù)流的組件举哟。通常情況下spout會從外部數(shù)據(jù)源中讀取數(shù)據(jù)思劳,然后轉(zhuǎn)換為topology內(nèi)部的源數(shù)據(jù)。
Bolt:接受數(shù)據(jù)然后執(zhí)行處理的組件,用戶可以在其中執(zhí)行自己想要的操作妨猩。
Tuple:一次消息傳遞的基本單元潜叛,理解為一組消息就是一個Tuple。
Stream:Tuple的集合壶硅。表示數(shù)據(jù)的流向威兜。
四、Topology運行
在Storm中,一個實時應(yīng)用的計算任務(wù)被打包作為Topology發(fā)布庐椒,這同Hadoop的MapReduce任務(wù)相似椒舵。但是有一點不同的是:在Hadoop中,MapReduce任務(wù)最終會執(zhí)行完成后結(jié)束约谈;而在Storm中笔宿,Topology任務(wù)一旦提交后永遠不會結(jié)束,除非你顯示去停止任務(wù)棱诱。計算任務(wù)Topology是由不同的Spouts和Bolts泼橘,通過數(shù)據(jù)流(Stream)連接起來的圖?一個Storm在集群上運行一個Topology時,主要通過以下3個實體來完成Topology的執(zhí)行工作:
(1). Worker(進程)
(2). Executor(線程)
(3). Task
下圖簡要描述了這3者之間的關(guān)系:
1個worker進程執(zhí)行的是1個topology的子集(注:不會出現(xiàn)1個worker為多個topology服務(wù))迈勋。1個worker進程會啟動1個或多個executor線程來執(zhí)行1個topology的component(spout或bolt)炬灭。因此,1個運行中的topology就是由集群中多臺物理機上的多個worker進程組成的粪躬。
executor是1個被worker進程啟動的單獨線程担败。每個executor只會運行1個topology的1個component(spout或bolt)的task(注:task可以是1個或多個,storm默認(rèn)是1個component只生成1個task镰官,executor線程里會在每次循環(huán)里順序調(diào)用所有task實例)。
task是最終運行spout或bolt中代碼的單元(注:1個task即為spout或bolt的1個實例吗货,executor線程在執(zhí)行期間會調(diào)用該task的nextTuple或execute方法)泳唠。topology啟動后,1個component(spout或bolt)的task數(shù)目是固定不變的宙搬,但該component使用的executor線程數(shù)可以動態(tài)調(diào)整(例如:1個executor線程可以執(zhí)行該component的1個或多個task實例)笨腥。這意味著,對于1個component存在這樣的條件:#threads<=#tasks(即:線程數(shù)小于等于task數(shù)目)勇垛。默認(rèn)情況下task的數(shù)目等于executor線程數(shù)目脖母,即1個executor線程只運行1個task。
總體的Topology處理流程圖為:
下圖是Storm的數(shù)據(jù)交互圖闲孤,可以看出兩個模塊Nimbus和Supervisor之間沒有直接交互谆级。狀態(tài)都是保存在Zookeeper上,Worker之間通過Netty傳送數(shù)據(jù)。Storm與Zookeeper之間的交互過程肥照,暫時不細(xì)說了脚仔。重要的一點:storm所有的元數(shù)據(jù)信息保存在Zookeeper中!
五舆绎、Storm Streaming Grouping
Storm中最重要的抽象鲤脏,應(yīng)該就是Stream grouping了,它能夠控制Spot/Bolt對應(yīng)的Task以什么樣的方式來分發(fā)Tuple吕朵,將Tuple發(fā)射到目的Spot/Bolt對應(yīng)的Task
目前猎醇,Storm Streaming Grouping支持如下幾種類型:
Shuffle Grouping :隨機分組,盡量均勻分布到下游Bolt中
將流分組定義為混排努溃。這種混排分組意味著來自Spout的輸入將混排姑食,或隨機分發(fā)給此Bolt中的任務(wù)。shuffle grouping對各個task的tuple分配的比較均勻茅坛。
Fields Grouping :按字段分組音半,按數(shù)據(jù)中field值進行分組;相同field值的Tuple被發(fā)送到相同的Task
這種grouping機制保證相同field值的tuple會去同一個task贡蓖,這對于WordCount來說非常關(guān)鍵曹鸠,如果同一個單詞不去同一個task,那么統(tǒng)計出來的單詞次數(shù)就不對了斥铺〕固遥“if the stream is grouped by the “user-id” field, tuples with the same “user-id” will alwaysGo to the same task”. —— 小示例
**All grouping **:廣播
廣播發(fā)送, 對于每一個tuple將會復(fù)制到每一個bolt中處理晾蜘。
Global grouping :全局分組邻眷,Tuple被分配到一個Bolt中的一個Task,實現(xiàn)事務(wù)性的Topology剔交。
Stream中的所有的tuple都會發(fā)送給同一個bolt任務(wù)處理肆饶,所有的tuple將會發(fā)送給擁有最小task_id的bolt任務(wù)處理。
None grouping :不分組
不關(guān)注并行處理負(fù)載均衡策略時使用該方式岖常,目前等同于shuffle grouping,另外storm將會把bolt任務(wù)和他的上游提供數(shù)據(jù)的任務(wù)安排在同一個線程下驯镊。
**Direct grouping **:直接分組 指定分組
由tuple的發(fā)射單元直接決定tuple將發(fā)射給那個bolt,一般情況下是由接收tuple的bolt決定接收哪個bolt發(fā)射的Tuple竭鞍。這是一種比較特別的分組方法板惑,用這種分組意味著消息的發(fā)送者指定由消息接收者的哪個task處理這個消息。 只有被聲明為Direct Stream的消息流可以聲明這種分組方法偎快。而且這種消息tuple必須使用emitDirect方法來發(fā)射冯乘。消息處理者可以通過TopologyContext來獲取處理它的消息的taskid (OutputCollector.emit方法也會返回taskid)。
另外晒夹,Storm還提供了用戶自定義Streaming Grouping接口裆馒,如果上述Streaming Grouping都無法滿足實際業(yè)務(wù)需求姊氓,也可以自己實現(xiàn),只需要實現(xiàn)backtype.storm.grouping.CustomStreamGrouping接口领追,該接口重定義了如下方法:
List chooseTasks(int taskId, List values)
上面幾種Streaming Group的內(nèi)置實現(xiàn)中他膳,最常用的應(yīng)該是Shuffle Grouping、Fields Grouping绒窑、Direct Grouping這三種棕孙,使用其它的也能滿足特定的應(yīng)用需求。
六些膨、可靠性
(1)蟀俊、spout的可靠性
spout會記錄它所發(fā)射出去的tuple,當(dāng)下游任意一個bolt處理失敗時spout能夠重新發(fā)射該tuple订雾。在spout的nextTuple()發(fā)送一個tuple時肢预,為實現(xiàn)可靠消息處理需要給每個spout發(fā)出的tuple帶上唯一ID,并將該ID作為參數(shù)傳遞給SpoutOutputCollector的emit()方法:collector.emit(new Values("value1","value2"), tupleID);
實際上Values extends ArrayList<Object>
保障過程中洼哎,每個bolt每收到一個tuple烫映,都要向上游應(yīng)答或報錯,在tuple樹上的所有bolt都確認(rèn)應(yīng)答噩峦,spout才會隱式調(diào)用ack()方法表明這條消息(一條完整的流)已經(jīng)處理完畢锭沟,將會對編號ID的消息應(yīng)答確認(rèn);處理報錯识补、超時則會調(diào)用fail()方法族淮。
(2)、bolt的可靠性
bolt的可靠消息處理機制包含兩個步驟:
a凭涂、當(dāng)發(fā)射衍生的tuple祝辣,需要錨定讀入的tuple
b、當(dāng)處理消息時切油,需要應(yīng)答或報錯
可以通過OutputCollector中emit()的一個重載函數(shù)錨定或tuple:collector.emit(tuple, new Values(word)); 并且需要調(diào)用一次this.collector.ack(tuple)應(yīng)答蝙斜。
七、總結(jié)
最后再來梳理一下Storm中涉及的主要概念
1.拓?fù)?Topology):打包好的實時應(yīng)用計算任務(wù)白翻,同Hadoop的MapReduce任務(wù)相似乍炉。
2.元組(Tuple):是Storm提供的一個輕量級的數(shù)據(jù)格式,可以用來包裝你需要實際處理的數(shù)據(jù)滤馍。
3.流(Streams):數(shù)據(jù)流(Stream)是Storm中對數(shù)據(jù)進行的抽象,它是時間上無界的tuple元組序列(無限的元組序列)?
4.Spout(噴嘴):Storm中流的來源底循。Spout從外部數(shù)據(jù)源巢株,如消息隊列中讀取元組數(shù)據(jù)并吐到拓?fù)淅铩?br>
5.Bolts:在拓?fù)渲兴械挠嬎氵壿嫸际窃贐olt中實現(xiàn)的。
6.任務(wù)(Tasks):每個Spout和Bolt會以多個任務(wù)(Task)的形式在集群上運行熙涤。
7.組件(Component):是對Bolt和Spout的統(tǒng)稱阁苞。
8.流分組(Stream groupings):流分組定義了一個流在一個消費它的Bolt內(nèi)的多個任務(wù)(task)之間如何分組困檩。
9.可靠性(Reliability):Storm保證了拓?fù)渲蠸pout產(chǎn)生的每個元組都會被處理。
10.Workers(工作進程):拓?fù)湟砸粋€或多個Worker進程的方式運行那槽。每個Worker進程是一個物理的Java虛擬機悼沿,執(zhí)行拓?fù)涞囊徊糠秩蝿?wù)。
11.Executor(線程):是1個被worker進程啟動的單獨線程骚灸。每個executor只會運行1個topology的1個component糟趾。
12.Nimbus:Storm集群的Master節(jié)點,負(fù)責(zé)分發(fā)用戶代碼甚牲,指派給具體的Supervisor節(jié)點上的Worker節(jié)點义郑,去運行Topology對應(yīng)的組件(Spout/Bolt)的Task。
13.Supervisor:Storm集群的從節(jié)點丈钙,負(fù)責(zé)管理運行在Supervisor節(jié)點上的每一個Worker進程的啟動和終止非驮。
參考:
http://www.cnblogs.com/swanspouse/p/5135679.html