轉載:https://www.cnblogs.com/Jack47/p/storm_intro-1.htmlhtml
本文是Storm系列之一,介紹了Storm的起源,Storm做者的八卦,Storm的特色和Storm模型的基本原理,着重介紹了Storm中的基本概念(Spout, Bolt, Stream, Tuple等)和對應的編程接口,能夠做爲Storm的入門文檔來閱讀。java
以前的技術文章都寫的有點一板一眼,太正經了。今天在文章正式開始前,跟你們八卦一下Storm的做者Nathan Marz吧。web
Storm的做者是Nathan Marz,Nathan Marz在BackType公司工做的時候有了Storm的點子並獨自一人實現了Storm。在2011年Twitter準備收購BackType之際,Nathan Marz爲了提升Twitter對BackType的估值,在一篇博客裏向外界介紹了Storm。Twitter對這項技術很是感興趣,所以在Twitter收購BackType的時候Storm發揮了重大做用。後來Nathan Marz開源Storm時,也藉着Twitter的品牌影響力而讓Storm名聲大震!算法
Storm的特色之一是可靠的消息處理機制,這個機制中最重要的一環是設計一個算法來跟蹤Storm中處理的數據,確保Storm知道消息是否被完整的處理。他創造出的這個算法,極大的簡化了系統的設計。Nathan Marz說這算法是他職業生涯中開發的最出色的算法之一,也說明了受過良好的計算機科學的教育是很是重要的。有趣的是發明這個算法的那天,正好是他和不久前遇到的一個姑娘約會的日子。當天由於發明了這個算法而很是興奮,致使他心思一直在這個算法上,毫無疑問就搞砸了和這個姑娘的約會!數據庫
Storm官方網站有段簡介apache
Storm是一個免費並開源的分佈式實時計算系統。利用Storm能夠很容易作到可靠地處理無限的數據流,像Hadoop批量處理大數據同樣,Storm能夠實時處理數據。Storm簡單,可使用任何編程語言。編程
在Storm以前,進行實時處理是很是痛苦的事情: 須要維護一堆消息隊列和消費者,他們構成了很是複雜的圖結構。消費者進程從隊列裏取消息,處理完成後,去更新數據庫,或者給其餘隊列發新消息。api
這樣進行實時處理是很是痛苦的。咱們主要的時間都花在關注往哪裏發消息,從哪裏接收消息,消息如何序列化,真正的業務邏輯只佔了源代碼的一小部分。一個應用程序的邏輯運行在不少worker上,但這些worker須要各自單獨部署,還須要部署消息隊列。最大問題是系統很脆弱,並且不是容錯的:須要本身保證消息隊列和worker進程工做正常。數組
Storm完整地解決了這些問題。它是爲分佈式場景而生的,抽象了消息傳遞,會自動地在集羣機器上併發地處理流式計算,讓你專一於實時處理的業務邏輯。安全
Storm有以下特色:
不過Storm不是一個完整的解決方案。使用Storm時你須要關注如下幾點:
跟Hadoop不同,Storm是沒有包括任何存儲概念的計算系統。這就讓Storm能夠用在多種不一樣的場景下:非傳統場景下數據動態到達或者數據存儲在數據庫這樣的存儲系統裏(或數據是被實時操控其餘設備的控制器(如交易系統)所消費)
Storm有不少應用:實時分析,在線機器學習(online machine learning),連續計算(continuous computation),分佈式遠程過程調用(RPC)、ETL等。Storm處理速度很快:每一個節點每秒鐘能夠處理超過百萬的數據組。它是可擴展(scalable),容錯(fault-tolerant),保證你的數據會被處理,而且很容易搭建和操做。
例如Nathan Marz提供的例子,產生Twitter的趨勢信息。Twitter從海量推文中抽取趨勢信息,並在本地區域和國家層級進行維護。這意味者一旦一個案例開始出現,Twitter的話題趨勢算法就能實時的鑑別出這個話題。這個實時的算法就是經過在Storm上連續分析Twitter數據來實現的。
下表列出了一組開源的大數據解決方案,包括傳統的批處理和流式處理的應用程序。
解決方案 | 開發者 | 類型 | 描述 |
---|---|---|---|
Storm | 流式處理 | Twitter的流式處理大數據分析方案 | |
S4 | Yahoo! | 流式處理 | Yahoo!的分佈式流式計算平臺 |
Hadoop | Apache | 批處理 | MapReduce範式的第一個開源實現 |
Spark | UC Berkeley AMPLab | 批處理 | 支持內存數據集和彈性恢復的分析平臺 |
Yahoo! S4和Storm之間的關鍵差異是Storm在故障的狀況下能夠保證消息的處理,而S4可能會丟消息。
Hadoop無疑是大數據分析的王者,本質上是一個批量處理系統,它專一於大數據的批量處理。數據存儲在Hadoop 文件系統裏(HDFS)並在處理的時候分發到集羣中的各個節點。當處理完成,產出的數據放回到HDFS上。在Storm上構建的拓撲處理的是持續不斷的流式數據。不一樣於Hadoop的任務,這些處理過程不會終止,會持續處理到達的數據。
Hadoop處理的是靜態的數據,而Storm處理的是動態的、連續的數據。Twitter的用戶天天都會發上千萬的推,因此這種處理技術是很是有用的。Storm不只僅是一個傳統的大數據分析系統:它是一個復瑣事件(complex event-processing)處理系統的例子。復瑣事件處理系統一般是面向檢測和計算的,這兩部分均可以經過用戶定義的算法在Storm中實現。例如,復瑣事件處理能夠用來從大量的事件中區分出有意義的事件,而後對這些事件實時處理。
Storm實現了一個數據流(data flow)的模型,在這個模型中數據持續不斷地流經一個由不少轉換實體構成的網絡。一個數據流的抽象叫作流(stream),流是無限的元組(Tuple)序列。元組就像一個能夠表示標準數據類型(例如int,float和byte數組)和用戶自定義類型(須要額外序列化代碼的)的數據結構。每一個流由一個惟一的ID來標示的,這個ID能夠用來構建拓撲中各個組件的數據源。
以下圖所示,其中的水龍頭表明了數據流的來源,一旦水龍頭打開,數據就會源源不斷地流經Bolt而被處理。圖中有三個流,用不一樣的顏色來表示,每一個數據流中流動的是元組(Tuple),它承載了具體的數據。元組經過流經不一樣的轉換實體而被處理。
Storm對數據輸入的來源和輸出數據的去向沒有作任何限制。像Hadoop,是須要把數據放到本身的文件系統HDFS裏的。在Storm裏,可使用任意來源的數據輸入和任意的數據輸出,只要你實現對應的代碼來獲取/寫入這些數據就能夠。典型場景下,輸入/輸出數據來是基於相似Kafka或者ActiveMQ這樣的消息隊列,可是數據庫,文件系統或者web服務也都是能夠的。
Storm中涉及的主要概念有:
能夠看到Storm中各個概念的名字起的很是好,也很形象。
一個Storm拓撲打包了一個實時處理程序的邏輯。一個Storm拓撲跟一個MapReduce的任務(job)是相似的。主要區別是MapReduce任務最終會結束,而拓撲會一直運行(固然直到你殺死它)。一個拓撲是一個經過流分組(stream grouping)把Spout和Bolt鏈接到一塊兒的拓撲結構。圖的每條邊表明一個Bolt訂閱了其餘Spout或者Bolt的輸出流。一個拓撲就是一個複雜的多階段的流計算。
元組是Storm提供的一個輕量級的數據格式,能夠用來包裝你須要實際處理的數據。元組是一次消息傳遞的基本單元。一個元組是一個命名的值列表,其中的每一個值均可以是任意類型的。元組是動態地進行類型轉化的--字段的類型不須要事先聲明。在Storm中編程時,就是在操做和轉換由元組組成的流。一般,元組包含整數,字節,字符串,浮點數,布爾值和字節數組等類型。要想在元組中使用自定義類型,就須要實現本身的序列化方式。
流是Storm中的核心抽象。一個流由無限的元組序列組成,這些元組會被分佈式並行地建立和處理。經過流中元組包含的字段名稱來定義這個流。
每一個流聲明時都被賦予了一個ID。只有一個流的Spout和Bolt很是常見,因此OutputFieldsDeclarer
提供了不須要指定ID來聲明一個流的函數(Spout和Bolt都須要聲明輸出的流)。這種狀況下,流的ID是默認的「default」。
Spout(噴嘴,這個名字很形象)是Storm中流的來源。一般Spout從外部數據源,如消息隊列中讀取元組數據並吐到拓撲裏。Spout能夠是可靠的(reliable)或者不可靠(unreliable)的。可靠的Spout可以在一個元組被Storm處理失敗時從新進行處理,而非可靠的Spout只是吐數據到拓撲裏,不關心處理成功仍是失敗了。
Spout能夠一次給多個流吐數據。此時須要經過OutputFieldsDeclarer
的declareStream
函數來聲明多個流並在調用SpoutOutputCollector
提供的emit
方法時指定元組吐給哪一個流。
Spout中最主要的函數是nextTuple
,Storm框架會不斷調用它去作元組的輪詢。若是沒有新的元組過來,就直接返回,不然把新元組吐到拓撲裏。nextTuple
必須是非阻塞的,由於Storm在同一個線程裏執行Spout的函數。
Spout中另外兩個主要的函數是ack
和fail
。當Storm檢測到一個從Spout吐出的元組在拓撲中成功處理完時調用ack
,沒有成功處理完時調用fail
。只有可靠型的Spout會調用ack
和fail
函數。更多細節能夠查看Storm Java文檔和個人另一篇文章:Storm如何保證可靠的消息處理
在拓撲中全部的計算邏輯都是在Bolt中實現的。一個Bolt能夠處理任意數量的輸入流,產生任意數量新的輸出流。Bolt能夠作函數處理,過濾,流的合併,聚合,存儲到數據庫等操做。Bolt就是流水線上的一個處理單元,把數據的計算處理過程合理的拆分到多個Bolt、合理設置Bolt的task數量,可以提升Bolt的處理能力,提高流水線的併發度。
Bolt能夠給多個流吐出元組數據。此時須要使用OutputFieldsDeclarer
的declareStream
方法來聲明多個流並在使用[OutputColletor](https://storm.apache.org/javadoc/apidocs/backtype/storm/task/OutputCollector.html)
的emit
方法時指定給哪一個流吐數據。
當你聲明瞭一個Bolt的輸入流,也就訂閱了另一個組件的某個特定的輸出流。若是但願訂閱另外一個組件的全部流,須要單獨挨個訂閱。InputDeclarer有語法糖來訂閱ID爲默認值的流。例如declarer.shuffleGrouping("redBolt")
訂閱了redBolt組件上的默認流,跟declarer.shuffleGrouping("redBolt", DEFAULT_STREAM_ID)
是相同的。
在Bolt中最主要的函數是execute
函數,它使用一個新的元組看成輸入。Bolt使用OutputCollector
對象來吐出新的元組。Bolts必須爲處理的每一個元組調用OutputCollector
的ack
方法以便於Storm知道元組何時被各個Bolt處理完了(最終就能夠確認Spout吐出的某個元組處理完了)。一般處理一個輸入的元組時,會基於這個元組吐出零個或者多個元組,而後確認(ack)輸入的元組處理完了,Storm提供了IBasicBolt接口來自動完成確認。
必須注意OutputCollector
不是線程安全的,因此全部的吐數據(emit)、確認(ack)、通知失敗(fail)必須發生在同一個線程裏。更多信息能夠參照問題定位。
每一個Spout和Bolt會以多個任務(Task)的形式在集羣上運行。每一個任務對應一個執行線程,流分組定義瞭如何從一組任務(同一個Bolt)發送元組到另一組任務(另一個Bolt)上。能夠在調用TopologyBuilder
的setSpout
和setBolt
函數時設置每一個Spout和Bolt的併發數。
組件(component)是對Bolt和Spout的統稱
定義拓撲的時候,一部分工做是指定每一個Bolt應該消費哪些流。流分組定義了一個流在一個消費它的Bolt內的多個任務(task)之間如何分組。流分組跟計算機網絡中的路由功能是相似的,決定了每一個元組在拓撲中的處理路線。
在Storm中有七個內置的流分組策略,你也能夠經過實現CustomStreamGrouping
接口來自定義一個流分組策略:
emitDirect
系列函數來吐元組給直連流。一個Bolt能夠經過提供的TopologyContext
來得到消費者的任務ID,也能夠經過OutputCollector對象的emit
函數(會返回元組被髮送到的任務的ID)來跟蹤消費者的任務ID。在ack的實現中,Spout有兩個直連輸入流,ack和ackFail,使用了這種直連分組的方式。TopologyBuilder
的setBolt
函數時會返回這個對象,它用來聲明一個Bolt的輸入流並指定流的分組方式。Storm保證了拓撲中Spout產生的每一個元組都會被處理。Storm是經過跟蹤每一個Spout所產生的全部元組構成的樹形結構並得知這棵樹什麼時候被完整地處理來達到可靠性。每一個拓撲對這些樹形結構都有一個關聯的「消息超時」。若是在這個超時時間裏Storm檢測到Spout產生的一個元組沒有被成功處理完,那Sput的這個元組就處理失敗了,後續會從新處理一遍。
爲了發揮Storm的可靠性,須要你在建立一個元組樹中的一條邊時告訴Storm,也須要在處理完每一個元組以後告訴Storm。這些都是經過Bolt吐元組數據用的OutputCollector
對象來完成的。標記是在emit
函數裏完成,完成一個元組後須要使用ack
函數來告訴Storm。
這些都在「保證消息處理」一文中會有更詳細的介紹。
拓撲以一個或多個Worker進程的方式運行。每一個Worker進程是一個物理的Java虛擬機,執行拓撲的一部分任務。例如,若是拓撲的併發設置成了300,分配了50個Worker,那麼每一個Worker執行6個任務(做爲Worker內部的線程)。Storm會盡可能把全部的任務均分到全部的Worker上。
ZeroMQ 提供了可擴展環境下的傳輸層高效消息通訊,一開始Storm的內部通訊使用的是ZeroMQ,後來做者想把Storm移交給Apache開源基金會來管理,而ZeroMQ的許可證書跟Apache基金會的政策有衝突。在Storm中,Netty比ZeroMQ更加高效,並且提供了worker間通訊時的驗證機制,因此在Storm0.9中,就改用了Netty。
Clojure Storm系統的實現語言。Clojure是由Rich Hicky做爲一種通用語言發明的,它衍生自Lisp語言,簡化了多線程編程。
Apache ZooKeeper Zookeeper是一個實現高可靠的分佈式協做的開源項目。Storm使用Zookeeper來協調集羣中的多個節點。
Storm簡介 這是淘寶主搜索的技術博客,文章通俗易懂
History of Apache Storm and lessons learned 推薦你們讀一讀,是Storm做者Nathan Marz寫的,文章講述了Storm的構思、建立過程和Storm的市場營銷,溝通交流和社區開發的故事。
twitter storm --IBM developerworks