【譯】Apache Storm系列 之一(核心概念)

Kooola大資料發表於2018-10-21

本文列出 Storm 的幾個主要概念,並會給出相關資源的連結以便你獲取更多資訊,概念主要如下:

  • Topologies
  • Streams
  • Spouts
  • Bolts
  • Stream groupings
  • Reliability
  • Tasks
  • Workers

拓撲(Topologies)

實時應用程式的邏輯被打包到 Storm 拓撲中。一個 Storm 拓撲類似於一個 MapReduce 任務。關鍵的區別在於 MapReduce 任務最終會結束,而拓撲會一直執行(當然,除非你強制 kill 掉拓撲相關的程式)。拓撲可以理解為通過資料流(Stream Grouping)將 Spout 和 Bolt 相互連線而組成的圖狀結構的程式。spouts 和 bolts 的概念會在下文介紹。

相關資源:

流(Streams)

流是 Storm 的核心抽象。Storm中,一個流指的是在分散式環境中被並行建立以及處理的元組(tuple)序列集。流是無限的元組(tuple)序列,以分散式方式並行建立和處理。流往往有固定的模式(我們稱之為“fields”),不同模式由不同的元組(tuple)型別以一定的方式組成。通常,元組(tuple)可以包含 integers, longs, shorts, bytes, strings, doubles, floats, booleans, 以及 byte arrays。當然,你也可以通過定義可序列化的物件來實現自定義的元組型別。

相關資源:

資料來源(Spouts)

在拓撲中, spout 是流的來源。通常情況,Spouts 會從外部源(例如訊息佇列或者 Twitter API)讀取資料並將資料傳送到拓撲中。Spouts 既可以是可靠的,也可以是不可靠的。可靠的情況是如果資料流沒有被 Storm 處理,Spouts 將重新傳送資料。不可靠的情況則是對傳送過的資料不予確認。

Spouts 一次可以傳送多個流。為了實現多流傳送,我們可以使用(實現) OutputFieldsDeclarer 介面中的 declareStream 方法來指定多個流,並使用(實現) SpoutOutputCollector 介面中的 emit 方法進行傳送。

nextTuple 是 Spouts 中的主要方法。nextTuple 方法要麼傳送一個新的元組到 topology 中,要麼直接返回(如果沒有新的元組需要傳送)。需要注意的是,nextTuple 不應該被 Spout 的任何其他方法所阻塞,否則會導致資料流的停止接入,這是因為 Spout 的所有方法是在一個執行緒中執行。

ack 和 fail 是 Spouts 中另外兩個重要的方法。Spouts 為可靠模式時,Storm 會檢測每一個從 Spouts 傳送出去的元組是否成功,成功呼叫 ack,失敗呼叫 fail。當然,在不可靠模式下,是不會呼叫這兩個方法的。

相關資源:

處理元件(Bolts)

topologies 所有的處理都是在 bolts 中進行。bolts 可以做很多事情,例如:過濾流、邏輯處理、聚合、連線、資料庫互動等等。

bolts 可以從事簡單的資料流轉換。處理複雜的資料流轉換通常需要將流程分成多步,這也就意味著我們可以使用多類(個) bolt。例如,從微博資料流中得出一個趨勢圖,實現這個需求我們至少需要兩步:第一個 bolt 計算每個圖片的點選數,第二個 bolt 在第一個基礎上得出 TOP X 的圖片(當然為了流程可擴充套件,我們可以使用更多的 bolt,不僅限於兩個)。

bolts 一次可以傳送多個流。為了實現多流傳送,我們可以使用(實現) OutputFieldsDeclarer 介面中的 declareStream 方法來指定多個流,並使用(實現) OutputCollector 介面中的 emit 方法進行傳送(跟 spout 類似)。

在定義 Bolt 的輸入資料流時,你需要從其他的 Storm 元件中訂閱指定的資料流。如果你需要從其他所有的元件中訂閱資料流,你就必須要在定義 Bolt 時分別註冊每一個元件。對於宣告為預設 id 的資料流,InputDeclarer 介面有訂閱此類資料流的語法糖。呼叫 declarer.shuffleGrouping("1") 將訂閱來自 id 為“1” 的元件(spout/bolt)產生的資料流,其等價於呼叫 declarer.shuffleGrouping("1", DEFAULT_STREAM_ID)

execute 是 bolt 的主要方法,它接收新的元組作為輸入。bolt 使用 OutputCollector 物件來傳送新的元組。bolt 必須為每個經由它處理的元組呼叫 OutputCollector 中的 ack 方法,這樣以便 Storm 知道這些元組什麼時候被處理完成(最終判斷對原始 spout 元組的響應是否合適)。處理元組的一般情況是,我們可以傳送多個元組或者直接不傳送,然後響應下一個輸入元組,我們可以實現 IBasicBolt 介面來完成 bolt 操作。

我們可以在 bolt 任務中開啟一個新的執行緒來完成非同步操作。OutputCollector 執行緒安全並且可以隨時被呼叫。

相關資源:

流分組(Stream groupings)

定義一個 topology 的重要一部分是指定每個 bolt 應該接收哪些流作為輸入。流分組(stream grouping)定義了流如何分發到各個 bolt 中。

Storm 提供了 8 種流分組策略。當然,你也可以通過實現 CustomStreamGrouping 介面來實現一個使用者自定義的流分組:

  • Shuffle grouping : 元組被隨機分發到各個 bolt 任務中,也就是說每個 bolt 接收到大致相同數目的元組。
  • Fields grouping : 根據指定的 field 進行分組 ,同一個 field 的值一定會被髮送到同一個 task 上。例如,如果流按照 "user-id" 這個 field 進行分組,那麼相同的 "user-id" 值會進入相同的任務(task),如果不同,則進入不同的任務。
  • Partial Key grouping : 與 Fields grouping 類似,根據指定的 field 的一部分進行分組分發,能夠很好地實現 load balance,將元組傳送給下游的 bolt 對應的 task,特別是在存在資料傾斜的場景,使用 Partial Key grouping 能夠更好地提高資源利用率
  • All grouping : 流複製到所有 bolt task 上。
  • Global grouping: 所有的流都指向一個 bolt 的同一個 task,也就是Task ID最小的。
  • None grouping : 使用這個分組,使用者不用關心流是如何進行分組的。目前,這個分組類似於 Shuffle grouping。不過未來 Storm 可能會考慮通過這種分組來讓 Bolt 和它所訂閱的 Spout 或 Bolt 在同一個執行緒中執行。
  • Direct grouping : 由 tupe 的生產者來決定傳送給下游的哪一個 bolt 的 task ,這個要在實際開發編寫 bolt 程式碼的邏輯中進行精確控制。
  • Local or shuffle grouping : 如果目標 bolt 有1個或多個 task 都在同一個 worker 程式對應的 JVM 例項中,則 tuple 只傳送給這些 task。

可靠性(Reliability)

Storm 保證每個 spout 元組都能在拓撲中被處理。通過跟蹤由 Spout 發出的每個元組構成的元組樹可以確定元組是否已經完成處理。每個拓撲都有與之相關的訊息超時。如果在超時時間內沒有檢測到元組是否被完整處理,該原則將會被標記並重新傳送。

想要使用 Storm 這個可靠性功能,你必須在元組建立以及處理完成時告訴 Storm。你可以使用用於傳送資料流的 OutputCollector 物件,並使用 ack 方法表明你已經完成了元組的處理。

任務(Tasks)

叢集中,每一個 spout 和 bolt 執行了多個任務。每個任務對應一個執行執行緒,流分組定義如何將元組從一組任務傳送到另一組任務。你可以使用 TopologyBuilder 中的 setSpout 和 setBolt 方法來設定任務並行度。

Workers

一個拓撲中執行了一個或多個 worker 程式。每個程式都是一個物理 JVM,並且拓撲中的所有 task 都在這些程式中執行。例如,如果並行度為 300,我們有 50 個worker 程式,那麼每個程式將處理 6 個 task。Storm 有其機制致力於將所有任務儘量平均地分配到每個程式中。

相關資源: Config.TOPOLOGY_WORKERS: 設定 worker 數量的配置


掃碼關注微信公眾號
掃碼關注微信公眾號"Kooola大資料",聊人生|聊技術

相關文章