Storm的BaseBasicBolt原始碼解析ack機制
我們在學習ack機制的時候,我們知道Storm的Bolt有BaseBasicBolt和BaseRichBolt。
在BaseBasicBolt中,BasicOutputCollector在emit資料的時候,會自動和輸入的tuple相關聯,而在execute方法結束的時候那個輸入tuple會被自動ack。
在使用BaseRichBolt需要在emit資料的時候,顯示指定該資料的源tuple要加上第二個引數anchor tuple,以保持tracker鏈路,即collector.emit(oldTuple, newTuple);並且需要在execute執行成功後呼叫OutputCollector.ack(tuple), 當失敗處理時,執行OutputCollector.fail(tuple);
那麼我們來看看BasicBolt的原始碼是不是這樣的,不能因為看到別人的帖子說是這樣的,我們就這樣任務,以訛傳訛,我們要To see is to believe。
為了方便看原始碼,我先上我們的繼承類:
public class SplitSentenceBolt extends BaseBasicBolt { public void prepare(Map stormConf, TopologyContext context) {
super.prepare(stormConf, context);
}
//5:執行我們自己的邏輯處理方法,接收傳入的引數。
public void execute(Tuple input, BasicOutputCollector collector) {
String sentence = (String)input.getValueByField("sentence");
String[] words = sentence.split(" ");
for (String word : words) {
word = word.trim();
word = word.toLowerCase();
collector.emit(new Values(word,1));//這個地方就是呼叫OutputCollector的包裝類,來發訊息
}
}
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(new Fields("word","num"));
}
}
通過打斷點,我們發現,bolt的task會建立這個類下面會標準執行順序
public class BasicBoltExecutor implements IRichBolt { public static Logger LOG = LoggerFactory.getLogger(BasicBoltExecutor.class); private IBasicBolt _bolt; private transient BasicOutputCollector _collector; //1:建立該物件,然後把我們寫的SplitSentenceBolt物件賦給父類IBasicBolt。 public BasicBoltExecutor(IBasicBolt bolt) { _bolt = bolt; } public void declareOutputFields(OutputFieldsDeclarer declarer) { _bolt.declareOutputFields(declarer);//這裡就是呼叫SplitSentenceBolt物件的方法了。 } //2:給BasicOutputCollector _collector欄位賦值,BasicOutputCollector就是對OutputCollector類的包裝。 public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) { _bolt.prepare(stormConf, context); _collector = new BasicOutputCollector(collector); } //3:然後程式執行該方法,input的值source: spout1:4, stream: default, id: {}, [+ - * % /] public void execute(Tuple input) { _collector.setContext(input);//把接收到的tuple值設定給BasicOutputCollector中inputTuple欄位。 try { _bolt.execute(input, _collector);//這個地方是呼叫我們實現類SplitSentenceBolt的ececute方法。 _collector.getOutputter().ack(input);//這個地方就是響應 } catch(FailedException e) { if(e instanceof ReportedFailedException) { _collector.reportError(e); } _collector.getOutputter().fail(input);//這個地方就是響應 } } public void cleanup() { _bolt.cleanup(); } public Map<String, Object> getComponentConfiguration() { return _bolt.getComponentConfiguration(); } }
public class BasicOutputCollector implements IBasicOutputCollector {
private OutputCollector out;
private Tuple inputTuple;
public BasicOutputCollector(OutputCollector out) {
this.out = out;
}
//4:把收到的tuple資料賦值給inputTuple,這個時候BasicOutputCollector物件的欄位都具有值了。
public void setContext(Tuple inputTuple) {
this.inputTuple = inputTuple;
}
//6:這裡我們傳送新的(轉換後的)tuple資料,看他內部的呼叫,其實他也會傳送一個anchor tuple來保持tracker鏈路,
而這個anchor tuple就是bolt接收到轉換前的源tuple資料。
public List<Integer> emit(List<Object> tuple) {
return emit(Utils.DEFAULT_STREAM_ID, tuple);
}
public List<Integer> emit(String streamId, List<Object> tuple) {
return out.emit(streamId, inputTuple, tuple);
}
public void emitDirect(int taskId, String streamId, List<Object> tuple) {
out.emitDirect(taskId, streamId, inputTuple, tuple);
}
public void emitDirect(int taskId, List<Object> tuple) {
emitDirect(taskId, Utils.DEFAULT_STREAM_ID, tuple);
}
protected IOutputCollector getOutputter() {
return out;
}
public void reportError(Throwable t) {
out.reportError(t);
}
}
這裡大家不要糾結bolt的啟動時從哪裡開始的,我後面會講的,這裡我們關注的是,BasicBoltExecutor物件建立後的執行過程,以這我們來看執行的過程。在BasicBoltExecutor的execute方法中,我們看到了ack和fail方法會被自動呼叫的,當我們的程式丟擲異常則會執行fail方法的。
作者:intsmaze(劉洋)
老鐵,你的—>推薦,—>關注,—>評論—>是我繼續寫作的動力。
微信公眾號號:Apache技術研究院
由於博主能力有限,文中可能存在描述不正確,歡迎指正、補充!
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。
相關文章
- Android AccessibilityService機制原始碼解析Android原始碼
- Dubbo原始碼解析之SPI機制原始碼
- Volley 原始碼解析之快取機制原始碼快取
- JDK原始碼解析之Java SPI機制JDK原始碼Java
- langchain chatchat執行機制原始碼解析LangChain原始碼
- Spark Shuffle機制詳細原始碼解析Spark原始碼
- Spring事件監聽機制原始碼解析Spring事件原始碼
- [原始碼解析] 從TimeoutException看Flink的心跳機制原始碼Exception
- Spring 原始碼解析一:SpringMVC 的載入機制原始碼SpringMVC
- 從原始碼的角度解析Mybatis的會話機制原始碼MyBatis會話
- React-原始碼解析-setState執行機制React原始碼
- Python記憶體管理機制-《原始碼解析》Python記憶體原始碼
- Android 9.0 原始碼_機制篇 -- 全面解析 HandlerAndroid原始碼
- 原始碼深度解析 Handler 機制及應用原始碼
- Android 事件分發機制原始碼解析-view層Android事件原始碼View
- Netty原始碼解析 -- 零拷貝機制與ByteBufNetty原始碼
- Handler訊息處理機制原始碼解析 上原始碼
- 從原始碼解析 Go 的切片型別以及擴容機制原始碼Go型別
- React 原始碼解析系列 - React 的 render 異常處理機制React原始碼
- 聊聊Dubbo – Dubbo可擴充套件機制原始碼解析套件原始碼
- 通過WordCount解析Spark RDD內部原始碼機制Spark原始碼
- Netty原始碼解析 -- 事件迴圈機制實現原理Netty原始碼事件
- Netty原始碼解析 -- ChannelPipeline機制與讀寫過程Netty原始碼
- Android原始碼解析之一 非同步訊息機制Android原始碼非同步
- ArrayList原始碼解析之fail-fast機制深入理解原始碼AIAST
- Qt原始碼解析之-從PIMPL機制到d指標QT原始碼指標
- [原始碼解析] TensorFlow 分散式環境(8) --- 通訊機制原始碼分散式
- JAVA訊息確認機制之ACK模式Java模式
- [原始碼解析] 並行分散式框架 Celery 之 容錯機制原始碼並行分散式框架
- RecyclerView 原始碼深入解析——繪製流程、快取機制、動畫等View原始碼快取動畫
- Timer機制原始碼淺析原始碼
- Dubbo 原始碼分析 - SPI 機制原始碼
- React原始碼分析 – 事件機制React原始碼事件
- ReactNative原始碼篇:通訊機制React原始碼
- Android 原始碼分析(二)handler 機制Android原始碼
- HashMap擴容機制原始碼分析HashMap原始碼
- webpack 原始碼探索之外掛機制Web原始碼
- Vue.js原始碼——事件機制Vue.js原始碼事件
- 從原始碼分析Hystrix工作機制原始碼