Apache Storm 官方文档 —— 源码组织结构
原文鏈接? ? 譯者:魏勇
Strom 的代碼有三個層次:
第一,Storm 在一開始就是按照兼容多語言的目的來設計的。Nimbus 是一個 Thrift 服務,拓撲也被定義為 Thrift 架構。Thrift 的使用使得 Storm 可以用于任何一種語言。
第二,所有的 Storm 接口都設計為 Java 接口。所以,盡管 Storm 核心代碼中有大量的 Clojure 實現(xiàn),所有的訪問都必須經(jīng)過 Java API。這就意味著 Storm 的每個特性都可以通過 Java 來實現(xiàn)。
第三,Storm 的實現(xiàn)中大量使用了 Clojure。可以說,Storm 的代碼結構大概是一半的 Java 代碼加上一半的 Clojure 代碼。但是由于 Clojure 更具有表現(xiàn)力,所以實際上 Storm 的核心邏輯大多是采用 Clojure 來實現(xiàn)的。
下面詳細說明了每個層次的細節(jié)信息。
storm.thrift
要理解 Storm 的代碼架構,首先需要了解 storm.thrift 文件。
Storm 使用這個 fork 版本的 Thrift(“storm” 分支)來生成代碼。這個 “fork” 版本實際上就是 Thrift7,其中所有的 Java package 也都重命名成了 org.apache.thrift7。在其他方面,它與 Thrift7 完全相同。這個 fork 主要是為了解決 Thrift 缺乏向后兼容的機制的問題,同時,也可以讓用戶在自己的 Storm 拓撲中使用其他版本的 Thrift。
拓撲中的每個 spout 或者 bolt 都有一個特定的標識,這個標識稱為“組件 id”。組件 id 主要為了從拓撲中 spout 和 bolt 的輸出流中選擇一個或多個流作為某個 bolt 訂閱的輸入流。Storm 拓撲中就包含有一個組件 id 與每種類型的組件(spout 與 bolt)相關聯(lián)的 map。
Spout 和 Bolt 有相同的 Thrift 定義。我們來看看 Bolt 的 Thrift 定義。它包含一個 ComponentObject 結構和一個ComponentCommon 結構。
ComponentObject 定義了 bolt 的實現(xiàn),這個實現(xiàn)可以是以下三種類型中的一種:
ComponentCommon 定義了組件的其他方面特性,包括:
注意,spout 的結構也有一個 ComponentCommon 域,所以理論上說 spout 也可以聲明一個輸入流。然而 Storm 的 Java API 并沒有為 spout 提供消費其他的流的方法,并且如果你為 spout 聲明了輸入流,在提交拓撲的時候也會報錯。這是因為 spout 的輸入流聲明不是為了用戶的使用,而是為了 Storm 內(nèi)部的使用。Storm 會為拓撲添加隱含的流與 bolt 來設置應答框架(acking framework)。這些隱含的流中就有兩個流用于從 acker bolt 向拓撲中的每個 spout 發(fā)送消息。在發(fā)現(xiàn) tuple 樹完成或者失敗之后,acker 就會通過這些隱含的流發(fā)送 “ack” 或者 “fail” 消息。將用戶的拓撲轉化為運行時拓撲的代碼在這里。
Java 接口
Storm 的對外接口基本上為 Java 接口,主要的幾個接口有:
大部分接口的策略為:
你可以從 BaseRichSpout 類中觀察到這種策略的工作機制。
如上所述,Spout 和 Bolt 都已經(jīng)根據(jù)拓撲的 Thrift 定義進行了序列化。
在這些接口中,IBolt、ISpout 與 IRichBolt、IRichSpout 之間存在著一些細微的差別。其中最主要的區(qū)別是帶有 “Rich” 的接口中增加了 declareOutputFields 方法。這種區(qū)別的原因主要在于每個輸出流的輸出域聲明必須是 Thrift 結構的一部分(這樣才能實現(xiàn)跨語言操作),而用戶本身只需要將流聲明為自己的類的一部分即可。TopologyBuilder 在構造 Thrift 結構時所做的就是調(diào)用 declareOutputFields 方法來獲取聲明并將其轉化為 Thrift 結構。這種轉化過程可以在TopologyBuilder 的源碼中看到。
實現(xiàn)
通過 Java 接口來詳細說明所有的功能可以確保 Storm 的每個特征都是有效的。更重要的是,關注 Java 接口可以讓有 Java 使用經(jīng)驗的用戶更易上手。
另一方面,Storm 的核心架構主要是通過 Clojure 實現(xiàn)的。盡管按照一般的計數(shù)規(guī)則來說代碼庫中 Java 與 Clojure 各占 50%,但是大部分邏輯實現(xiàn)還是基于 Clojure 的。不過也有兩個例外,分別是 DRPC 和事務型拓撲的實現(xiàn)。這兩個部分是完全使用 Java 實現(xiàn)的。這是為了說明在 Storm 中如何實現(xiàn)高級抽象。DRPC 和事務型拓撲的實現(xiàn)分別位于backtype.storm.coordination、backtype.storm.drpc 和 backtype.storm.transactional 包中。
以下是主要的 Java 包和 Clojure 命名空間的總結。
Java packages
backtype.storm.coordination: 實現(xiàn)了用于將批處理整合到 Storm 上層的功能,DRPC 和事務型拓撲都需要這個功能。CoordinatedBolt 是其中最重要的類。
backtype.storm.drpc: DRPC 高級抽象的實現(xiàn)。
backtype.storm.generated: 為 Storm 生成的 Thrift 代碼(使用了這個 fork 版本的 Thrift,其中僅僅將包名重命名為 org.apache.thrift7 來避免與其他 Thrift 版本的沖突)。
backtype.storm.grouping: 包含自定義流分組的接口。
backtype.storm.hooks: 用于在 Storm 中添加事件鉤子的接口,這些事件包括任務發(fā)送 tuple、tuple 被 ack 等等。
backtype.storm.serialization: Storm 序列化/反序列化 tuple 的接口。這是在 Kryo 的基礎上構建的。
backtype.storm.spout: Spout 與一些關聯(lián)接口的定義(例如 SpoutOutputCollector)。其中也包含有用于實現(xiàn)非 JVM 語言 spout 的協(xié)議的 ShellSpout。
backtype.storm.task: Bolt 與關聯(lián)接口的定義(例如 OutputCollector)。其中也包含有用于實現(xiàn)非 JVM 語言 bolt 的協(xié)議的 ShellBolt。最后,TopologyContext 也是在這里定義的,該類可以用于在拓撲運行時為 spout 和 bolt 提供拓撲以及他們自身執(zhí)行的相關信息。
backtype.storm.testing: 包含很多 bolt 測試類以及用于 Storm 單元測試的工具類。
backtype.storm.topology: 在 Thrift 結構上層的 Java 層,用于為 Storm 提供完全的 Java API(用戶不必了解 Thrift)。TopologyBuilder 和一些為不同的 spout 和 bolt 提供幫助的基礎類都在這里。稍微高級一點的 IBasicBolt 接口也在這里,該接口是一種實現(xiàn)基本的 bolt 的簡單方式。
backtype.storm.transactional: 事務型拓撲的實現(xiàn)。
backtype.storm.tuple: Storm tuple 數(shù)據(jù)模型的實現(xiàn)。
backtype.storm.utils: 整個代碼庫中通用的數(shù)據(jù)結構和各種工具類。
Clojure namespaces
譯者注:Clojure 部分內(nèi)容暫不提供翻譯。
總結
以上是生活随笔為你收集整理的Apache Storm 官方文档 —— 源码组织结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android: 播放音频
- 下一篇: 一个word文档中,多个表格的批量调整(