storm基本概念

Storm 系統(tǒng)中包含以下幾個(gè)基本概念:
拓?fù)洌═opologies)
流(Streams)
數(shù)據(jù)源(Spouts)
數(shù)據(jù)流處理組件(Bolts)
數(shù)據(jù)流分組(Stream groupings)
可靠性(Reliability)
任務(wù)(Tasks)
工作進(jìn)程(Workers)

譯者注:由于 Storm 的幾個(gè)基礎(chǔ)概念無(wú)論是直譯還是意譯均不夠清晰,而且還會(huì)讓習(xí)慣了 Storm 編程模型的讀者感到困惑,因此后文在提及這些概念時(shí)大多還會(huì)以英文原文出現(xiàn),希望大家能夠諒解。

拓?fù)洌═opologies)
Storm 的拓?fù)涫菍?duì)實(shí)時(shí)計(jì)算應(yīng)用邏輯的封裝,它的作用與 MapReduce 的任務(wù)(Job)很相似,區(qū)別在于 MapReduce 的一個(gè) Job 在得到結(jié)果之后總會(huì)結(jié)束,而拓?fù)鋾?huì)一直在集群中運(yùn)行,直到你手動(dòng)去終止它。拓?fù)溥€可以理解成由一系列通過(guò)數(shù)據(jù)流(Stream Grouping)相互關(guān)聯(lián)的 Spout 和 Bolt 組成的的拓?fù)浣Y(jié)構(gòu)。Spout 和 Bolt 稱為拓?fù)涞慕M件(Component)。我們會(huì)在后文中給出這些概念的解釋。
相關(guān)資料
TopologyBuilder:在 Java 中使用此類(lèi)構(gòu)造拓?fù)?br> 在生產(chǎn)環(huán)境中運(yùn)行拓?fù)?/a>
本地模式:通過(guò)本文學(xué)習(xí)如何在本地模式中開(kāi)發(fā)、測(cè)試拓?fù)?/p>

數(shù)據(jù)流(Streams)
數(shù)據(jù)流(Streams)是 Storm 中最核心的抽象概念。一個(gè)數(shù)據(jù)流指的是在分布式環(huán)境中并行創(chuàng)建、處理的一組元組(tuple)的無(wú)界序列。數(shù)據(jù)流可以由一種能夠表述數(shù)據(jù)流中元組的域(fields)的模式來(lái)定義。在默認(rèn)情況下,元組(tuple)包含有整型(Integer)數(shù)字、長(zhǎng)整型(Long)數(shù)字、短整型(Short)數(shù)字、字節(jié)(Byte)、雙精度浮點(diǎn)數(shù)(Double)、單精度浮點(diǎn)數(shù)(Float)、布爾值以及字節(jié)數(shù)組等基本類(lèi)型對(duì)象。當(dāng)然,你也可以通過(guò)定義可序列化的對(duì)象來(lái)實(shí)現(xiàn)自定義的元組類(lèi)型。
在聲明數(shù)據(jù)流的時(shí)候需要給數(shù)據(jù)流定義一個(gè)有效的 id。不過(guò),由于在實(shí)際應(yīng)用中使用最多的還是單一數(shù)據(jù)流的 Spout 與 Bolt,這種場(chǎng)景下不需要使用 id 來(lái)區(qū)分?jǐn)?shù)據(jù)流,因此可以直接使用 OutputFieldsDeclarer來(lái)定義“無(wú) id”的數(shù)據(jù)流。實(shí)際上,系統(tǒng)默認(rèn)會(huì)給這種數(shù)據(jù)流定義一個(gè)名為“default”的 id。
相關(guān)資料
元組(Tuple):數(shù)據(jù)流由多個(gè)元組構(gòu)成
OutputFieldsDeclarer:用于聲明數(shù)據(jù)流和數(shù)據(jù)流對(duì)應(yīng)的模式
序列化(Serialization):關(guān)于 Storm 元組的動(dòng)態(tài)類(lèi)型以及聲明自定義序列化模型的相關(guān)內(nèi)容
ISerialization:自定義的序列化模型必須實(shí)現(xiàn)該接口
CONFIG.TOPOLOGY_SERIALIZATIONS:自定義的序列化模型可以通過(guò)這個(gè)配置項(xiàng)實(shí)現(xiàn)注冊(cè)

數(shù)據(jù)源(Spouts)
數(shù)據(jù)源(Spout)是拓?fù)渲袛?shù)據(jù)流的來(lái)源。一般 Spout 會(huì)從一個(gè)外部的數(shù)據(jù)源讀取元組然后將他們發(fā)送到拓?fù)渲小8鶕?jù)需求的不同,Spout 既可以定義為可靠的數(shù)據(jù)源,也可以定義為不可靠的數(shù)據(jù)源。一個(gè)可靠的 Spout 能夠在它發(fā)送的元組處理失敗時(shí)重新發(fā)送該元組,以確保所有的元組都能得到正確的處理;相對(duì)應(yīng)的,不可靠的 Spout 就不會(huì)在元組發(fā)送之后對(duì)元組進(jìn)行任何其他的處理。
一個(gè) Spout 可以發(fā)送多個(gè)數(shù)據(jù)流。為了實(shí)現(xiàn)這個(gè)功能,可以先通過(guò) OutputFieldsDeclarer 的 declareStream
方法來(lái)聲明定義不同的數(shù)據(jù)流,然后在發(fā)送數(shù)據(jù)時(shí)在 SpoutOutputCollector 的 emit
方法中將數(shù)據(jù)流 id 作為參數(shù)來(lái)實(shí)現(xiàn)數(shù)據(jù)發(fā)送的功能。
Spout 中的關(guān)鍵方法是 nextTuple
。顧名思義,nextTuple
要么會(huì)向拓?fù)渲邪l(fā)送一個(gè)新的元組,要么會(huì)在沒(méi)有可發(fā)送的元組時(shí)直接返回。需要特別注意的是,由于 Storm 是在同一個(gè)線程中調(diào)用所有的 Spout 方法,nextTuple
不能被 Spout 的任何其他功能方法所阻塞,否則會(huì)直接導(dǎo)致數(shù)據(jù)流的中斷(關(guān)于這一點(diǎn),阿里的 JStorm 修改了 Spout 的模型,使用不同的線程來(lái)處理消息的發(fā)送,這種做法有利有弊,好處在于可以更加靈活地實(shí)現(xiàn) Spout,壞處在于系統(tǒng)的調(diào)度模型更加復(fù)雜,如何取舍還是要看具體的需求場(chǎng)景吧——譯者注)。
Spout 中另外兩個(gè)關(guān)鍵方法是 ack
和 fail
,他們分別用于在 Storm 檢測(cè)到一個(gè)發(fā)送過(guò)的元組已經(jīng)被成功處理或處理失敗后的進(jìn)一步處理。注意,ack
和 fail
方法僅僅對(duì)上述“可靠的” Spout 有效。
相關(guān)資料
IRichSpout:這是實(shí)現(xiàn) Spout 的接口
消息的可靠性處理

數(shù)據(jù)流處理組件(Bolts)
拓?fù)渲兴械臄?shù)據(jù)處理均是由 Bolt 完成的。通過(guò)數(shù)據(jù)過(guò)濾(filtering)、函數(shù)處理(functions)、聚合(aggregations)、聯(lián)結(jié)(joins)、數(shù)據(jù)庫(kù)交互等功能,Bolt 幾乎能夠完成任何一種數(shù)據(jù)處理需求。
一個(gè) Bolt 可以實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)流轉(zhuǎn)換,而更復(fù)雜的數(shù)據(jù)流變換通常需要使用多個(gè) Bolt 并通過(guò)多個(gè)步驟完成。例如,將一個(gè)微博數(shù)據(jù)流轉(zhuǎn)換成一個(gè)趨勢(shì)圖像的數(shù)據(jù)流至少包含兩個(gè)步驟:其中一個(gè) Bolt 用于對(duì)每個(gè)圖片的微博轉(zhuǎn)發(fā)進(jìn)行滾動(dòng)計(jì)數(shù),另一個(gè)或多個(gè) Bolt 將數(shù)據(jù)流輸出為“轉(zhuǎn)發(fā)最多的圖片”結(jié)果(相對(duì)于使用2個(gè)Bolt,如果使用3個(gè) Bolt 你可以讓這種轉(zhuǎn)換具有更好的可擴(kuò)展性)。
與 Spout 相同,Bolt 也可以輸出多個(gè)數(shù)據(jù)流。為了實(shí)現(xiàn)這個(gè)功能,可以先通過(guò) OutputFieldsDeclarer 的 declareStream
方法來(lái)聲明定義不同的數(shù)據(jù)流,然后在發(fā)送數(shù)據(jù)時(shí)在 OutputCollector 的 emit
方法中將數(shù)據(jù)流 id 作為參數(shù)來(lái)實(shí)現(xiàn)數(shù)據(jù)發(fā)送的功能。
在定義 Bolt 的輸入數(shù)據(jù)流時(shí),你需要從其他的 Storm 組件中訂閱指定的數(shù)據(jù)流。如果你需要從其他所有的組件中訂閱數(shù)據(jù)流,你就必須要在定義 Bolt 時(shí)分別注冊(cè)每一個(gè)組件。對(duì)于聲明為默認(rèn) id(即上文中提到的“default”——譯者注)的數(shù)據(jù)流,InputDeclarer支持訂閱此類(lèi)數(shù)據(jù)流的語(yǔ)法糖。也就是說(shuō),如果需要訂閱來(lái)自組件“1”的數(shù)據(jù)流,declarer.shuffleGrouping("1")
與 declarer.shuffleGrouping("1", DEFAULT_STREAM_ID)
兩種聲明方式是等價(jià)的。
Bolt 的關(guān)鍵方法是 execute
方法。execute
方法負(fù)責(zé)接收一個(gè)元組作為輸入,并且使用 OutputCollector 對(duì)象發(fā)送新的元組。如果有消息可靠性保障的需求,Bolt 必須為它所處理的每個(gè)元組調(diào)用 OutputCollector
的 ack
方法,以便 Storm 能夠了解元組是否處理完成(并且最終決定是否可以響應(yīng)最初的 Spout 輸出元組樹(shù))。一般情況下,對(duì)于每個(gè)輸入元組,在處理之后可以根據(jù)需要選擇不發(fā)送還是發(fā)送多個(gè)新元組,然后再響應(yīng)(ack)輸入元組。IBasicBolt 接口能夠?qū)崿F(xiàn)元組的自動(dòng)應(yīng)答。
在 Bolt 中啟動(dòng)新線程來(lái)進(jìn)行異步處理是一種非常好的方式,因?yàn)?OutputCollector 是線程安全的對(duì)象,可以在任意時(shí)刻被調(diào)用(此處譯者保留意見(jiàn),由于 Storm 的并發(fā)設(shè)計(jì)和集群的彈性擴(kuò)展機(jī)制,在 Bolt 中新建的線程可能存在一定的不可控風(fēng)險(xiǎn)——譯者注)。
請(qǐng)注意 OutputCollector 不是線程安全的對(duì)象,所有的 emit、ack 和 fail 操作都需要在同一個(gè)線程中進(jìn)行處理。更多信息請(qǐng)參考問(wèn)題與解決一文。
相關(guān)資料
IRichBolt:用于定義 Bolt 的基本接口
IBasicBolt: 用于定義帶有過(guò)濾或者其他簡(jiǎn)單的函數(shù)操作功能的 Bolt 的簡(jiǎn)便接口
OutputCollector:Bolt 使用此類(lèi)來(lái)發(fā)送數(shù)據(jù)流
消息的可靠性處理

數(shù)據(jù)流分組(Stream groupings)
為拓?fù)渲械拿總€(gè) Bolt 的確定輸入數(shù)據(jù)流是定義一個(gè)拓?fù)涞闹匾h(huán)節(jié)。數(shù)據(jù)流分組定義了在 Bolt 的不同任務(wù)(tasks)中劃分?jǐn)?shù)據(jù)流的方式。
在 Storm 中有八種內(nèi)置的數(shù)據(jù)流分組方式(原文有誤,現(xiàn)在已經(jīng)已經(jīng)有八種分組模型——譯者注),而且你還可以通過(guò)CustomStreamGrouping 接口實(shí)現(xiàn)自定義的數(shù)據(jù)流分組模型。這八種分組分時(shí)分別為:
隨機(jī)分組(Shuffle grouping):這種方式下元組會(huì)被盡可能隨機(jī)地分配到 Bolt 的不同任務(wù)(tasks)中,使得每個(gè)任務(wù)所處理元組數(shù)量能夠能夠保持基本一致,以確保集群的負(fù)載均衡。
域分組(Fields grouping):這種方式下數(shù)據(jù)流根據(jù)定義的“域”來(lái)進(jìn)行分組。例如,如果某個(gè)數(shù)據(jù)流是基于一個(gè)名為“user-id”的域進(jìn)行分組的,那么所有包含相同的“user-id”的元組都會(huì)被分配到同一個(gè)任務(wù)中,這樣就可以確保消息處理的一致性。
部分關(guān)鍵字分組(Partial Key grouping):這種方式與域分組很相似,根據(jù)定義的域來(lái)對(duì)數(shù)據(jù)流進(jìn)行分組,不同的是,這種方式會(huì)考慮下游 Bolt 數(shù)據(jù)處理的均衡性問(wèn)題,在輸入數(shù)據(jù)源關(guān)鍵字不平衡時(shí)會(huì)有更好的性能1
。感興趣的讀者可以參考這篇論文,其中詳細(xì)解釋了這種分組方式的工作原理以及它的優(yōu)點(diǎn)。
完全分組(All grouping):這種方式下數(shù)據(jù)流會(huì)被同時(shí)發(fā)送到 Bolt 的所有任務(wù)中(也就是說(shuō)同一個(gè)元組會(huì)被復(fù)制多份然后被所有的任務(wù)處理),使用這種分組方式要特別小心。
全局分組(Global grouping):這種方式下所有的數(shù)據(jù)流都會(huì)被發(fā)送到 Bolt 的同一個(gè)任務(wù)中,也就是 id 最小的那個(gè)任務(wù)。
非分組(None grouping):使用這種方式說(shuō)明你不關(guān)心數(shù)據(jù)流如何分組。目前這種方式的結(jié)果與隨機(jī)分組完全等效,不過(guò)未來(lái) Storm 社區(qū)可能會(huì)考慮通過(guò)非分組方式來(lái)讓 Bolt 和它所訂閱的 Spout 或 Bolt 在同一個(gè)線程中執(zhí)行。
直接分組(Direct grouping):這是一種特殊的分組方式。使用這種方式意味著元組的發(fā)送者可以指定下游的哪個(gè)任務(wù)可以接收這個(gè)元組。只有在數(shù)據(jù)流被聲明為直接數(shù)據(jù)流時(shí)才能夠使用直接分組方式。使用直接數(shù)據(jù)流發(fā)送元組需要使用 OutputCollector 的其中一個(gè) emitDirect 方法。Bolt 可以通過(guò) TopologyContext 來(lái)獲取它的下游消費(fèi)者的任務(wù) id,也可以通過(guò)跟蹤 OutputCollector 的 emit
方法(該方法會(huì)返回它所發(fā)送元組的目標(biāo)任務(wù)的 id)的數(shù)據(jù)來(lái)獲取任務(wù) id。
本地或隨機(jī)分組(Local or shuffle grouping):如果在源組件的 worker 進(jìn)程里目標(biāo) Bolt 有一個(gè)或更多的任務(wù)線程,元組會(huì)被隨機(jī)分配到那些同進(jìn)程的任務(wù)中。換句話說(shuō),這與隨機(jī)分組的方式具有相似的效果。

相關(guān)資料
TopologyBuilder:使用此類(lèi)構(gòu)造拓?fù)?br> InputDeclarer:在 TopologyBuilder
中調(diào)用 setBolt
方法時(shí)會(huì)返回這個(gè)對(duì)象的實(shí)例,通過(guò)該對(duì)象就可以定義 Bolt 的輸入數(shù)據(jù)流以及數(shù)據(jù)流的分組方式
CoordinatedBolt:這個(gè) Bolt 主要用于分布式 RPC 拓?fù)洌渲写罅渴褂昧酥苯訑?shù)據(jù)流與直接分組模型

可靠性(Reliability)
Storm 可以通過(guò)拓?fù)鋪?lái)確保每個(gè)發(fā)送的元組都能得到正確處理。通過(guò)跟蹤由 Spout 發(fā)出的每個(gè)元組構(gòu)成的元組樹(shù)可以確定元組是否已經(jīng)完成處理。每個(gè)拓?fù)涠加幸粋€(gè)“消息延時(shí)”參數(shù),如果 Storm 在延時(shí)時(shí)間內(nèi)沒(méi)有檢測(cè)到元組是否處理完成,就會(huì)將該元組標(biāo)記為處理失敗,并會(huì)在稍后重新發(fā)送該元組。
為了充分利用 Storm 的可靠性機(jī)制,你必須在元組樹(shù)創(chuàng)建新結(jié)點(diǎn)的時(shí)候以及元組處理完成的時(shí)候通知 Storm。這個(gè)過(guò)程可以在 Bolt 發(fā)送元組時(shí)通過(guò) OutputCollector 實(shí)現(xiàn):在 emit
方法中實(shí)現(xiàn)元組的錨定(Anchoring),同時(shí)使用 ack
方法表明你已經(jīng)完成了元組的處理。
關(guān)于可靠性保障的更多內(nèi)容可以參考這篇文章:消息的可靠性處理
任務(wù)(Tasks)
在 Storm 集群中每個(gè) Spout 和 Bolt 都由若干個(gè)任務(wù)(tasks)來(lái)執(zhí)行。每個(gè)任務(wù)都與一個(gè)執(zhí)行線程相對(duì)應(yīng)。數(shù)據(jù)流分組可以決定如何由一組任務(wù)向另一組任務(wù)發(fā)送元組。你可以在 TopologyBuilder 的 setSpout
方法和 setBolt
方法中設(shè)置 Spout/Bolt 的并行度。
工作進(jìn)程(Workers)
拓?fù)涫窃谝粋€(gè)或多個(gè)工作進(jìn)程(worker processes)中運(yùn)行的。每個(gè)工作進(jìn)程都是一個(gè)實(shí)際的 JVM 進(jìn)程,并且執(zhí)行拓?fù)涞囊粋€(gè)子集。例如,如果拓?fù)涞牟⑿卸榷x為300,工作進(jìn)程數(shù)定義為50,那么每個(gè)工作進(jìn)程就會(huì)執(zhí)行6個(gè)任務(wù)(進(jìn)程內(nèi)部的線程)。Storm 會(huì)在所有的 worker 中分散任務(wù),以便實(shí)現(xiàn)集群的負(fù)載均衡。
相關(guān)資料
Config.TOPOLOGY_WORKERS:這個(gè)配置項(xiàng)用于設(shè)置拓?fù)涞墓ぷ鬟M(jìn)程數(shù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 本文主要介紹storm中的基本概念,從基礎(chǔ)上了解strom的體系結(jié)構(gòu),便于后續(xù)編程過(guò)程中作為基礎(chǔ)指導(dǎo)。主要的概念包...
    看山遠(yuǎn)兮閱讀 1,574評(píng)論 0 9
  • 一、Storm是什么 Storm是一個(gè)免費(fèi)并開(kāi)源的分布式實(shí)時(shí)計(jì)算系統(tǒng)。利用Storm可以很容易做到可靠地處理無(wú)限的...
    Graceleeman閱讀 3,050評(píng)論 0 6
  • 流式計(jì)算中,各個(gè)中間件產(chǎn)品對(duì)計(jì)算過(guò)程中的角色的抽象都不盡相同,實(shí)現(xiàn)方式也是千差萬(wàn)別。本文針對(duì)storm中間件在進(jìn)行...
    一品悟技術(shù)_張馳閱讀 2,568評(píng)論 0 1
  • Date: Nov 17-24, 2017 1. 目的 積累Storm為主的流式大數(shù)據(jù)處理平臺(tái)對(duì)實(shí)時(shí)數(shù)據(jù)處理的相關(guān)...
    一只很努力爬樹(shù)的貓閱讀 2,206評(píng)論 0 4
  • 萬(wàn)賤賤穿心 第一次寫(xiě)連載,也不知道怎么玩,想到哪兒算哪兒吧。反正我也沒(méi)多少文采,唯求寫(xiě)得接地氣一點(diǎn),大...
    一朵煙花的貓咪閱讀 257評(píng)論 0 1