像Apache Storm一樣簡單的分布式圖計算

摘要:本文從計算機領域的“祖師爺”艾倫·圖靈提出的圖靈機概念開始,介紹了圖形計算的概念,并以示例介紹了apache storm,基于apache storm如何進行分布式圖形計算。apache storm是一個免費開源的分布式實時計算系統,具有簡單易用、快速、可擴展、容錯等優點。

介紹

計算可能很復雜。對我們來說,這種復雜主要就是軟件世界的人類驅動力。甚至有一個學科整個都圍繞著問題解決和計算——計算機科學。

當一個人開始學習計算機科學時,會被介紹一些術語和概念,這些術語和概念都是圍繞著試圖以可證明,恰當的方式對問題的解決方案進行建模和表達而形成的。

艾倫·圖靈

艾倫·圖靈 天才地提出了 圖靈機 的概念。這些“機器”使我們能夠以數學證明的方式恰如其分地描述解決方案,同樣也適用于解決計算機科學領域遇到的問題。

圖片由 維基本科 提供。

從那時起,圍繞抽象計算機(包括圖靈機)的整個研究發展起來,名為 自動機理論的研究

自動機理論的領域是廣泛的,也是在不斷增長和最流行的 — 因為它可以生成能夠解決現實生活中問題的模型。

圖片由 維基本科 提供。

在一定程度上,自動機理論與 圖論 是密切相關的。

結合這兩種理論的優點,我們能夠設計出可證明的、分布式的、有效的解決問題的方案,否則這些問題將會太過于復雜,難以表達和解決。

在本文中,將介紹 Apache Storm (從現在開始使用術語“Storm” – 通常是指Apache的Storm版本。storm中的spout譯為“噴嘴”,bolt譯為“螺栓”),作為分布式圖形計算基礎架構的實現。

接下來就開始吧!

圖形計算作為降低系統復雜度的一種方式

在介紹了圖靈機、自動機理論和圖論之后,圖形計算可以作為一種降低系統復雜度的方式嗎?

答案是肯定的。

依靠一個經過測試和證明的模型,并不一定意味著 使用 這個模型和 證明 它一樣復雜。

例如下面的表達式:

1 + 1 = 2

大家都“知道”它是正確的,并且能夠使用它,因為已經有人 證明 它是正確的。

在本文的例子中,試圖將一個已知的問題轉化為一個圖形計算,其中每個 頂點 都是一個計算單元。根據連接它們的邊,在頂點之間“移動”。

接下來看下面的例子:

想要實現一個應用程序執行以下任務:

  1. 它接收一個訂單請求作為輸入。
  2. 如果訂單有效,就會向倉庫發送包裝和運輸請求,并通知客戶訂單成功。
  3. 如果訂單無效,則通知客戶。

把手頭的任務看作是一個圖形計算,可以將其描述如下:

以圖形的方式思考問題有一些好處。

首先,有了圖形以后,人類的思維更容易理解,不至于那么抽象了。

其次,鼓勵我們遵循良好務實的軟件設計原則,如 關注點分離 原則。每個頂點只做一件事。

再次,它使我們看到每個頂點所做的事,并將其外包給基礎架構。

例如,每個頂點接收并可能發送消息。以 容錯 的方式負責 外包 處理 傳入和傳出消息 是非常可取的。

部署也可以通過這種方式變得 更加靈活 — 例如,可以部署一臺單獨計算機的每個計算單元,并讓基礎架構去負責固有的消息傳遞和分發。

負載均衡和 可擴展性 如何?可以依靠“外部”消息傳遞系統來管理同一計算單元的多個實例嗎?答案是肯定的!

如果在訂單驗證過程中遇到瓶頸,是否可以實例化一個額外的驗證計算單元并讓它處理一些工作呢?可以的。

現在請記住,我們已經在圖中描述了應該如何處理每個輸入消息。還沒有描述過如何部署它。

所以 我們也分開 考慮了軟件的 正確性 和軟件的 部署 問題。

可能的情況是,除了將實例化兩個計算單元的驗證頂點之外,還為每個“邏輯”圖形頂點實例化一個物理計算單元,如下圖所示:

前面提到的關于關注點分離的提示,利用適當的基礎架構,可以處理進程間的通信,給出不同的部署需求(每個組織/個人),以容錯和可擴展的方式,旨在找準問題。

圖形計算確實是有用的,幫助我們考慮軟件解決方案,同時把軟件部署排除在外 —只要有適當的基礎架構,就可以做到這一點。

Apache Storm提供了以圖形方式編寫計算的能力,同時提供了一個固有的基礎架構,使我們能夠可靠高效地完成這些計算。

Apache Storm的方式

Apache Storm中,主要應用程序被稱為拓撲(topology),也就是Storm拓撲。

每個拓撲代表一個永遠在線的應用程序,它可以接收來自被稱為 噴嘴 (spout)的數據源的輸入。

噴嘴是輸入消息的來源,稱為 元組 。元組是動態類型的,它的成員可以是任何類型 —只要Storm“知道”如何序列化和反序列化這些類型。

元組正在按照拓撲的定義在 螺栓 ( bolt)之間傳遞。每個螺栓都可以傳遞元組到其它螺栓,只要它們連接到它。一個螺栓可以修改一個元組或者創建一個新的元組。它也可以按原樣傳遞傳入的元組,或者根本不傳遞任何東西。

元組通過噴嘴的元組流向被稱為 。多個流可以共存于一個拓撲中。每個數據流都與其它數據流并行處理。稍后將會再講到這一點。

Storm極具融合性,并與其它技術很好地集成。它能夠使用 ElasticsearchMongodbKafkaRedisKinesis 等基礎架構。如果需要自定義的東西,這也是可能的,Storm有一個很大的并在不斷發展的庫生態系統。

所以,如果想用一句話總結一下“Storm方式”的話,我會說:

Apache Storm是一種分布式技術,旨在允許開發人員利用圖形計算模型為問題同時提供“底層”(例如消息負載均衡)和“頂層“(例如準備使用Kafka Spout - 只需配置和使用來自Kafka的數據)的邏輯解決方案。

Apache Storm概述

為了更好地了解Storm如何工作,需要暫時縮小范圍。

本文不會對技術本身進行深入地研究。但是,如果想更好地了解該技術,包括部署的演示,與其它技術的集成和監控,請參閱我的課程, 在這里

從宏觀上看看Storm集群是如何建立的。這將有助于了解它是如何提供上述基礎架構的,比如計算圖形部分之間的可靠消息傳遞,以及某種程度的并行性,文章將在后面作進一步解釋。

首先,storm集群是由(不足為奇)…節點構建而成的。這些節點可以采用任何一個主節點的形式運行 Nimbus 守護進程或者采用 工作進程(worker)節點的形式 —運行 Supervisor 守護進程。它采用主從架構方式,主節點是Nimbus,從節點是Supervisor,有關調度相關的信息存儲在Zookeeper集群中。

主節點負責在工作節點之間分配工作。分配什么工作呢?實現圖形計算的實際代碼作為拓撲傳遞給Storm集群。

主節點和工作節點如何相互認知?通過 Zookeeper 。Zookeeper是一個分布式服務,作為一個可靠的配置和同步提供者。要了解更多關于Zookeeper的信息,包括安裝和集成演示,請看看 這里

所以說主節點負責將代碼分發給工作節點。但是,這里還有一個額外的抽象層: 工作進程

一個工作 進程 負責執行拓撲的一個子集。每個工作進程將實例化執行 任務 實例的執行器線程。這些任務可以是 噴嘴螺栓

雖然理解起來可能相當困難,但是這種結構確實具有在各種物理機器,進程和線程之間分配邏輯計算圖形的能力,從而使storm集群在硬件故障的情況下 保持邏輯計算完整性

一個工作進程掛了?沒問題 —主節點會將其工作分配給另一個工作節點。

請注意,看起來主節點似乎是一個單點故障點。事實并不是這樣。即使主節點發生故障或崩潰,拓撲仍將繼續執行。顯然,我們將無法向集群提交新拓撲,因為主節點有責任在工作節點之間進行代碼共享,但是在線計算將繼續下去。

這種不希望發生的情況可以通過在Storm集群(又名Nimbus H / A)中定義多個主節點來彌補。這樣的話,一個失敗的主節點將會被一個健康的主節點替換。

現在應該能夠更好地理解Storm是如何將計算圖形和 物理 硬件層(主節點和工作節點,zookeeper,執行進程中的工作進程和任務)的 邏輯 概念完全分離開來的(拓撲結構是由噴嘴和螺栓與元組之間的流動建立起來的)。

這種架構是團隊之間關注點分離的推動者。可以將處理邏輯層的任務分配給開發人員,也可以將處理物理層的任務分配給DevOps工程師。

開發Storm的工程師考慮了上述關注點分離的概念,并向開發人員提供了在開發人員的機器上 本地運行拓撲 的思路。

談論開發人員—不如看一些代碼?

示例拓撲—讓我們看一些代碼

好吧,有些人可能以為在進行訂單驗證,包裝和裝運時,這個例子并不太適合演示圖形計算。

我不這么認為。圖形計算,就像任何其它模型一樣都是一個工具。作為開發人員,軟件架構師和/或研發副總裁,都需要決定這個工具是否適合手頭上的任務。我認為對于高吞吐量的電子商務網站,Storm實際上非常適合作為一個穩定的后臺。

接下來看看如何將上述用例作為一個Storm的拓撲實現。

首先,需要建立一個新的項目,就用一個Maven項目來展示。已經將以下依賴項添加到 pom.xml 文件中:

首先創建一個使用由Storm提供的 TopologyBuilder 的拓撲:

為了設置拓撲噴嘴,調用 TopologyBuilder 實例上的 setSpout 方法,傳遞一個噴嘴ID和一個噴嘴實例。

這是進入圖形計算的切入點。這也可能是一個 KafkaSpout 。

現在有信息進入系統,就想消化它。有時間在拓撲中添加一些螺栓。

把每一個螺栓連接到拓撲,將提供如下信息:

  1. 在拓撲中唯一標識它的螺栓ID。
  2. 它在拓撲中的前身,以及首選的分組方法。
  3. 一個可選的流ID。

2和3很快就會提到。

那么接下來看看帶有所有螺栓的拓撲:

每一次添加一個螺栓到拓撲,都調用 setBolt 。

然后,給螺栓命名,并為該螺栓提供一個實例。該實例是根據每個螺栓所需邏輯實現的類。接下來看一下這樣的螺栓。

每個螺栓,已經連接到另一個螺栓或噴嘴,并提供輸入。

在驗證螺栓的情況下,有兩種可能的結果(有效的或無效的),根據每個可能的結果,已經創建了一個只在特定流(驗證螺栓正在向其發送消息)上偵聽消息的螺栓。

現在來觀察一個螺栓的實現。為了符合Storm的架構,需要執行什么?

這里可以看到已經擴展了 BaseRichBolt 類。為了符合其定義,必須實現三種方法。

正如它名字暗示的那樣,這個 prepare 方法是一個占位符,一旦元組到達它,就可以執行螺栓所需的任何必要的初始化,以實現恰當的功能。在大多數情況下,至少會將輸出收集器引用保存到局部變量中。輸出收集器允許發出新的元組到下面的螺栓。

它也允許 確認 一個元組。Storm會將任何未確認的元組視為一個未處理的數據結構,以便重新處理。

execute 方法在每個元組傳遞時(由Storm基礎結構)調用一次。在execute方法中將使用元組,在需要的情況下發出任何新的元組,最后,確認傳入的元組。

當想要傳遞一個特定的字段到下一個螺栓時, declareOutputFields 方法是必需的。例如, PackageGenerationBolt 傳遞以一個字段名為“ShipmentRequest”的裝運請求到下一個螺栓(ShipmentRequestBolt)時,要知道如何引用:

最后,將拓撲提交到集群并運行它。在這個例子中,提交給一個專門為調試而開發的本地集群:

一旦拓撲經過測試和調試,就可以安全地將其部署到 “真實”的Storm集群。

這可以通過幾種方式來完成。

一般來說,需要將拓撲連同所有相關的依賴項打包到jar文件中,并將其傳遞給Storm集群。通過使用命令行來完成更簡單。

如果想看到一個“真實的”的demo,請查看 這里

如何進行分布式計算?

太神奇了!現在明白了,把許多計算分解成圖形的邏輯和物理形式并不是很難,因為頂點以“標準”形式(序列化元組)進行通信。

現在也知道代碼是如何在Storm集群上執行的。

在將拓撲提交給集群后,打包成一個jar文件,拓撲組件(即spouts和bolt)被部署到各個storm工作節點(由主節點決定),并在工作節點中實例化——封裝在任務線程中,存在執行過程中。

Storm基礎架構知道拓撲內流動的數據流。這個基礎架構還通過螺栓跟蹤元組確認,為我們提供了可靠的消息傳遞系統。

內在的并行性:作為并行度的流

圖形計算的好處之一是,可以在應用程序中清晰地顯示單獨的計算路徑。

看看這里:

有什么東西阻止并行處理兩種不同的數據流嗎?當然沒有,這是Storm的完美任務!

流是 Storm中的 一種并行的程度 。所有的流元組都將流經相關的螺栓(如拓撲所描述的那樣),而不知道拓撲中的其它流。

螺栓(bolt)的實例

這是一個好的開始,是不是?不同的流可以分別單獨處理。然而,還有另外一種并行度—在 任務層面 的并行度。作為一個優秀的學生,應該記住任務可以是噴嘴或螺栓的形式。

定義拓撲時,可以聲明每個噴嘴或螺栓所需的并行度。

請注意,不希望任務沒有控制的按需產生!太多的任務(即線程)會引入過度并行,并可能導致集群“慢下來”,最終讓應用程序變得無法響應。

在使用Storm的并行度功能之前,請考慮 想達到的并行度并提供可用的資源

假設有3個Storm工作進程節點,并且部署了一個具有一個并行度設置為2的單個噴嘴的拓撲,以及5個并行度設置為2的螺栓 — storm將為噴嘴生成2個任務,每個螺栓生成5 * 2 = 10 個任務。

這意味著將有12個任務,storm集群將試圖均勻地分布在3個工作節點上(下圖沒有畫出所有的線以避免混亂)。

作為內部“秩序者”的分組

還是回到 分組 的概念。

之前已經看到,當創建一個螺栓時,已經指定了它的“輸入”螺栓:

但是這樣做的方式還不清楚,正如我們所說的那樣,需要一個“隨機分組”

奇怪,不是嗎?分組與之前建立的圖形拓撲有什么關系?難道不是所有的流元組都只是從一個螺栓流到另一個螺栓嗎?

那么請記住,噴嘴和螺栓可以有多個實例,以便進行分布式并行計算。

雖然 噴嘴螺栓 在邏輯上是一個原子計算單元,但它的物理實現并不一定。

分組是定義兩個不同拓撲元素之間的元組流的方式。它將定義輸入實體和目標實體的實例(任務)之間的元組是如何流動的。

例如,“shuffleGrouping”將隨機發送元組到螺栓實例。

提醒一下,在討論分組時,討論的是兩個實體之間的數據流,并且只有兩個實體。

在這里,可以看到每個元組是如何隨機地轉移到一個螺栓實例(任務),從PackageGenerationBolt到ShipmentRequestBolt。

一個最有趣的分組選項是“字段”分組,在這個分組中指定要將元組分組的特定字段。例如,分組 ShipmentRequestBolt 到基于字段“WarehouseId”的 PackageGenerationRequest 。由于這種“字段”的分組策略,所有帶有相同 WarehouseId 值的元組,在輸入元組時始終被定向到相同的 ShipmentRequestBolt 任務實例。

還有其它有趣的分組方法可以在 這里查看

結論

感謝大家與我一起度過這段短暫的旅程,總體地回顧了圖形計算的概念和Apache Storm更具體的細節。在寫這篇文章的時候,我一直牢記“保持簡單”,假設一旦“理解了”這個想法并理解了這個工具,將能夠決定你是否需要對Storm進行更深入的研究。這也是我提到額外的閱讀和我的Pluralsight課程的原因。

我們從理解圖形計算是什么以及它起源于何處開始了這一旅程。特別是理解了它在計算機科學領域是多么深奧的概念。

一旦確信(希望),我們已經開始討論支持基礎架構的好處,以便可靠地將應用程序作為圖形計算實現。

我們介紹了Apache Storm這樣一種技術。

storm在邏輯層、拓撲層和物理層——物理集群本身進行了回顧。

理解了拓撲如何在整個集群中傳播,并在物理層的最終抽象層(任務)中執行。

然后討論了Storm如何提供并行度— 無論是在流級別和還是在特定任務級別(噴嘴或螺栓)。

看一些代碼,我試圖傳遞使用storm的簡單和美麗。

希望已經成功地吸引了你。

 

來自:http://www.iteye.com/news/32830

 

 本文由用戶 winner1125 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!