網址: http://xumingming.sinaapp.com/811/twitter-storm-code-analysis-coordinated-bolt/
關於Twitter Storm的新特性:Transactional Topology被問到的最多的問題是:
Storm是怎麼知道一個Bolt處理完成了它所有的tuple的?其實要做到這一點還是有蠻多事情要做的, 幸運的是Storm已經提供了一個Bolt,幫我們把這些事情都做掉了。這個牛逼的bolt就是
CoordinatedBolt. 重要的是CoordinatedBolt
的實現也是在storm的原語:spout, bolt這些基礎之上的 — 也就是說即使作者不提供,我們自己也可以實現。我們來看看這個類的實現原理。
雖然CoordinatedBolt所發揮的作用很牛逼,但是其實它的原理並不是很複雜。它現在被用在兩個場景裏面:
- DRPC
- Transactional Topology
在看CoordinatedBolt
的原理之前,我們先看看到底什麼叫”處理完了”, 到底處理完什麼了?
其實CoordinatedBolt對於業務不是完全沒有侵入的,要使用CoordinatedBolt提供的功能,你必須要保證你的每個bolt發送的每個tuple的第一個field是request-id
, 那麼所謂的”做完了”的意思是說當前這個bolt對於當前這個”request-id”所需要做的工作做完了。 這個request-id
在DRPC
裏面代表一個DRPC請求;在Transactional Topology裏面代表一個batch.
CoordinatedBolt的原理是這樣的:
- 對於用戶在DRPC, Transactional Topology裏面的Bolt,都被CoordinatedBolt包裝了一層:也就是說在DRPC, Transactional Topology裏面的topology裏面運行的已經不是用戶提供的原始的Bolt, 而是一堆CoordinatedBolt, CoordinatedBolt把這些Bolt的事務都代理了。
- 有了這個代理層,CoordinatedBolt就可以做它的工作了。
- 它會在自己這裏維護以下幾個數據:
- 哪些上游task要給我發tuple?(通過構造topology的時候所提供的grouping信息可以得知)
- 我給哪些下游task發tuple? (同樣通過grouping信息可以得知)
- 每個CoordinatedBolt在每次真正bolt發出一個tuple之後,它都會記錄下,這個tuple發給哪個task了。
- 等它所有的tuple都發送完了之後(怎麼知道發送完了?等會再說,少安毋躁),它通過另外一個特殊的stream以emitDirect的方式告訴所有它發送過tuple的task,它發送了多少tuple給它。
- 一個bolt在接到所有的上游task發送的tuple個數信息之後,對比它接收到的tuple數量,如果數量對上了,說明它接收到了所有的tuple — 它處理完成了。
- 這樣它處理完成了,它可以重複上面的步驟通知它的下游,它的下游再通知它的下游的下游等等。
- 總結一下,每個tuple怎麼知道自己處理完成了的?都是靠它的上游通知的。所以只要一個bolt有上游,它就能夠知道自己什麼時候完成。
- 那總有一個bolt是沒有上游的 — 最上面那個bolt。那麼這個bolt是怎麼知道自己處理完成的呢?靠的是storm的ack系統 — 只要它ack了它的上游(某個非CoordinatedBolt, 在DRPC裏面就是PrepareRequest)發送過來的tuple, 它就完成處理這個tuple了。 — 也就是說對於最上面那個bolt來說它只要處理完一個tuple(相對於它的下游要處理很多tuple纔算完成)
具體原理如下圖:
正如我們在上面討論到底什麼叫”做完成”的概念的時候,我們說了,CoordinatedBolt
的使用對於業務是有侵入的:你必須要在你的每個tuple的第一個字段帶上當前request-id
, 否則CoordinatedBolt
就跟蹤不了了。 一種更優雅的方式是網絡協議棧裏面IP, TCP協議的處理方式。IP包在TCP包的外面包上IP層需要的信息,而不要求把IP層需要的信息摻雜在TCP的包字段裏面,TCP層在發送數據的時候只組裝TCP的那些字段,到了IP層自動加上IP層的信息。而IP層把數據包傳給TCP層之前也自動去掉IP層的那些信息,TCP只會看到自己層的那些字段,毫無侵入。。作者對於這個問題提了一些改進的措施在這裏