三、訊息的可靠處理
1、訊息被完全處理的含義
當樹建立完畢,並且樹中的每一個訊息都已經被處理時,Storm認為來自Spout的元組是“完全處理”的。當一個元組的訊息樹在指定的超時範圍內不能被完全處理,則元組被認為是失敗的。
2、如果一個訊息被完全處理或完全處理失敗會發生什麼
首先,讓我們看看Spout的元組的生命週期。ISpout介面的定義如下:
public interface ISpout extends Serializable {
void open(Map conf, TopologyContext context, SpoutOutputCollector colle- ctor);
void close();
void nextTuple();
void ack(Object msgId);
void fail(Object msgId);
}
首先,Storm通過呼叫Spout的nextTuple()方法從Spout請求一個元組。Spout使用open()方法提供的SpoutOutputCollector物件發射一個元組到它的輸出流。當發射元組時,Spout會提供一個“訊息id”,以便用來識別元組。例如,KestrelSpout從Kestrel訊息佇列中讀取一個訊息時,會發射Kestrel提供的“訊息id”。下面發射一個訊息到SpoutOutputCollector物件:
_collector.emit(new Values("field1", "field2", 3) , msgId);
接下來,元組被髮送到Bolt,同時Storm負責跟蹤建立的訊息樹。如果Storm檢測到一個元組是完全處理的,Storm將呼叫原Spout任務的ack()方法,把Spout提供給Storm的訊息id作為輸入引數。同樣,如果元組超時,Storm將呼叫Spout的fail()方法。注意,一個元組將由Spout任務來確認成功或失敗,這個Spout任務是建立此元組的完全相同的Spout任務。如果一個Spout跨叢集執行很多工,元組是不會被建立它的那個任務外的其他任務確認成功或失敗的。
注意:bolt是沒有ack()和fail()函式的,任何訊息出錯了,都是由根spout重發
3、Storm如何保證可靠性
在元組樹中指定一個連結,此連結被稱為錨定(Anchoring)。Anchoring在發射一個新的元組的同一時間完成。讓我們使用以下Bolt為例進行介紹,這個Bolt將包含一個句子的元組劃分為一個包含每個單詞的錨定:
public class SplitSentence extends BaseRichBolt {
OutputCollector _collector;
public void prepare(Map conf, TopologyContext context, OutputCollector
collector) {
_collector = collector;
}
public void execute(Tuple tuple) {
String sentence = tuple.getString(0);
for(String word: sentence.split(" ")) {
_collector.emit(tuple, new Values(word));//錨定+發射
}
_collector.ack(tuple);//確認
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}<
通過指定輸入元組作為第一個引數來發射,每個單詞元組被錨定(anchored)。因為這個單詞元組是被錨定的,如果單詞元組未能被下游處理,樹的根的Spout元組將在稍後重發。相反,如果單詞元組的發射操作如下,讓我們看看會發生什麼:
_collector.emit(new Values(word));
這種方式發射的單詞元組導致未被錨定(unanchored)。如果元組未被下游處理,根元組將不會重發。這取決於你需要的Topology的容錯保證,有時候需要相應地發射一個未被錨定的元組。
很多Bolt遵循一個讀取一個輸入元組,發射元組,在execute方法確認元組的通用模式。這些Bolt具有類別過濾器和簡單的功能。Storm有一個介面稱為BasicBolt,為你封裝這個模式。SplitSentence的例子可以使用BasicBolt寫成:
public class SplitSentence extends BaseBasicBolt {
public void execute(Tuple tuple, BasicOutputCollector collector) {
String sentence = tuple.getString(0);
for(String word: sentence.split(" ")) {
collector.emit(new Values(word));
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word"));
}
}
這個實現與之前的實現相比,語義上是相同的,但是更簡單。元組發射到BasicOutputCollectorare是自動Anchoring到輸入元組,當execute方法完成時,輸入元組自動為你確認。
storm系統中有一組叫做acker(可以設定並行度為多個)的特殊任務,它負責跟蹤DAG中的每個訊息。每當發現一個DAG被完全處理,它就向建立這個根訊息的Spout任務傳送一個訊號,該tuple tree已經被完全處理成功。
系統使用一種雜湊演算法根據Spout訊息的id來確定由哪個acker跟蹤此訊息派生出來的tuple tree。因為每個訊息都知道與之對應的根訊息的id(每當Bolt新生成一個訊息,對應的tuple tree中的根訊息id就複製到這個訊息中),所以它知道應該與哪個acker通訊。當這個訊息被應答的時候,它就把關於tuple tree變化的資訊傳送給跟蹤這棵樹的acker。例如,它會告訴acker:“本訊息已經處理完畢,但是我派生出來了一些新的訊息,幫忙跟蹤一下吧”。
一個Acker任務儲存來自Spout元組id到一對值的對映。第一個值是建立Spout元組的任務id,通過這個ID,acker就知道訊息處理完成時該通知哪個spout任務。第二個值是一個64位的值,稱為ack val。它是所有訊息的隨機id的異或結果,當一個Acker任務看到ack val已經成為0,它就知道元組樹已經完成了。
相關文章
- php ActiveMQ的傳送訊息,與處理訊息PHPMQ
- IOS 訊息推送處理iOS
- RabbitMQ 訊息的可靠投遞MQ
- MPLS RSVP訊息處理——VecloudCloud
- Storm保證訊息處理ORM
- C#的訊息處理方法 (轉)C#
- RabbitMQ的訊息可靠性(五)MQ
- 訊息佇列之如何保證訊息的可靠傳輸佇列
- Rabbitmq可靠訊息投遞,訊息確認機制MQ
- .net core 訊息流處理流程
- VCL中訊息處理初探 (轉)
- Go 語言的錯誤訊息處理Go
- 如何處理RabbitMQ 訊息堆積和訊息丟失問題MQ
- 處理鍵盤輸入訊息(轉)
- Windows應用程式的訊息處理機制Windows
- Looper中的訊息佇列處理機制OOP佇列
- struts 如何能夠報處理正常的訊息
- C++ BUILDER 訊息處理的深入探索 (轉)C++UI
- 《RabbitMQ》如何保證訊息的可靠性MQ
- 訊息中介軟體消費到的訊息處理失敗怎麼辦?
- 【實戰教程】微信卡券訊息處理
- Storm基礎(四)保證訊息處理ORM
- 使用 Java API 處理 WebSphere MQ 大訊息JavaAPIWebMQ
- Android中的非同步訊息處理機制Android非同步
- KafkaConsumer對於事務訊息的處理Kafka
- RocketMQ的事務訊息處理【half-message】MQ
- MFC應用程式中處理訊息的順序
- 分散式事務:訊息可靠傳送分散式
- java從SQS訂閱訊息 的demo, 要求保證訊息可靠投遞的例子Java
- 如何用 Golang 的 channel 實現訊息的批次處理Golang
- 如何用 Golang 的 channel 實現訊息的批量處理Golang
- 請教mina處理訊息?需要建立訊息佇列?佇列
- Redis 使用 List 實現訊息佇列能保證訊息可靠麼?Redis佇列
- RabbitMQ,RocketMQ,Kafka 事務性,訊息丟失和訊息重複傳送的處理策略MQKafka
- MFC動態建立控制元件的訊息處理 (轉)控制元件
- 原始碼分析:Android訊息處理機制原始碼Android
- Android應用程式訊息處理機制Android
- 如何處理錯誤訊息PleaseinstalltheLinuxkernelheaderfilesLinuxHeader