Apache 流框架 Flink,Spark Streaming,Storm對比分析 (二)

2.Spark Streaming架構及特性分析


2.1 基本架構

?基于是spark core的spark streaming架構。


Spark Streaming是將流式計算分解成一系列短小的批處理作業。這里的批處理引擎是Spark,也就是把Spark Streaming的輸入數 據按照batch size(如1秒)分成一段一段的數據(Discretized Stream),每一段數據都轉換成Spark中的RDD(Resilient Distributed Dataset ) , 然 后 將 Spark Streaming 中 對 DStream 的 Transformation 操 作 變 為 針 對 Spark 中 對 RDD 的 Transformation操作,將RDD經 過操作變成中間結果保存在內存中。整個流式計算根據業務的需求可以對中間的結果進行疊加, 或者存儲到外部設備。

簡而言之,Spark Streaming把實時輸入數據流以時間片Δt (如1秒)為單位切分成塊,Spark Streaming會把每塊數據作為一個 RDD,并使用RDD操作處理每一小塊數據。每個塊都會生成一個Spark Job處理,然后分批次提交job到集群中去運行,運行每個 job的過程和真正的spark 任務沒有任何區別。


JobScheduler


負責job的調度

JobScheduler是SparkStreaming 所有Job調度的中心, JobScheduler的啟動會導致ReceiverTracker和JobGenerator的啟動。 ReceiverTracker的啟動導致運行在Executor端的Receiver啟動并且接收數據,ReceiverTracker會記錄Receiver接收到的數據 meta信息。JobGenerator的啟動導致每隔BatchDuration,就調用DStreamGraph生成RDD Graph,并生成Job。JobScheduler 中的線程池來提交封裝的JobSet對象(時間值,Job,數據源的meta)。Job中封裝了業務邏輯,導致最后一個RDD的action被觸 發,被DAGScheduler真正調度在Spark集群上執行該Job。


JobGenerator


負責Job的生成

通過定時器每隔一段時間根據Dstream的依賴關系生一個一個DAG圖。


ReceiverTracker


負責數據的接收,管理和分配

ReceiverTracker在啟動Receiver的時候他有ReceiverSupervisor,其實現是ReceiverSupervisorImpl, ReceiverSupervisor本身啟 動的時候會啟動Receiver,Receiver不斷的接收數據,通過BlockGenerator將數據轉換成Block。定時器會不斷的把Block數據通會不斷的把Block數據通過BlockManager或者WAL進行存儲,數據存儲之后ReceiverSupervisorlmpl會把存儲后的數據的元數據Metadate匯報給ReceiverTracker,其實是匯報給ReceiverTracker中的RPC實體ReceiverTrackerEndpoint,主要。


2.2 基于Yarn層面的架構分析

上圖為spark on yarn 的cluster模式,Spark on Yarn啟動后,由Spark AppMaster中的driver(在AM的里面會啟動driver,主要 是StreamingContext對象)把Receiver作為一個Task提交給某一個Spark Executor;Receive啟動后輸入數據,生成數據塊,然 后通知Spark AppMaster;Spark AppMaster會根據數據塊生成相應的Job,并把Job的Task提交給空閑Spark Executor 執行。圖 中藍色的粗箭頭顯示被處理的數據流,輸入數據流可以是磁盤、網絡和HDFS等,輸出可以是HDFS,數據庫等。對比Flink和spark streaming的cluster模式可以發現,都是AM里面的組件(Flink是JM,spark streaming是Driver)承載了task的分配和調度,其他 container承載了任務的執行(Flink是TM,spark streaming是Executor),不同的是spark streaming每個批次都要與driver進行 通信來進行重新調度,這樣延遲性遠低于Flink。

具體實現

圖2.1 Spark Streaming程序轉換為DStream Graph

圖2.2 DStream Graph轉換為RDD的Graph

Spark Core處理的每一步都是基于RDD的,RDD之間有依賴關系。下圖中的RDD的DAG顯示的是有3個Action,會觸發3個job, RDD自下向上依 賴,RDD產生job就會具體的執行。從DSteam Graph中可以看到,DStream的邏輯與RDD基本一致,它就是在 RDD的基礎上加上了時間的依賴。RDD的DAG又可以叫空間維度,也就是說整個 Spark Streaming多了一個時間維度,也可以成 為時空維度,使用Spark Streaming編寫的程序與編寫Spark程序非常相似,在Spark程序中,主要通過操作RDD(Resilient Distributed Datasets彈性分布式數據集)提供的接口,如map、reduce、filter等,實現數據的批處理。而在Spark Streaming 中,則通過操作DStream(表示數據流的RDD序列)提供的接口,這些接口和RDD提供的接口類似。


Spark Streaming把程序中對 DStream的操作轉換為DStream Graph,圖2.1中,對于每個時間片,DStream Graph都會產生一個RDD Graph;針對每個輸出 操作(如print、foreach等),Spark Streaming都會創建一個Spark action;對于每個Spark action,Spark Streaming都會產生 一個相應的Spark job,并交給JobScheduler。JobScheduler中維護著一個Jobs隊列, Spark job存儲在這個隊列中, JobScheduler把Spark job提交給Spark Scheduler,Spark Scheduler負責調度Task到相應的Spark Executor上執行,最后形成 spark的job。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖2.3時間維度生成RDD的DAG

Y軸就是對RDD的操作,RDD的依賴關系構成了整個job的邏輯,而X軸就是時間。隨著時間的流逝,固定的時間間隔(Batch Interval)就會生成一個job實例,進而在集群中運行。


代碼實現

基于spark 1.5的spark streaming源代碼解讀,基本架構是沒怎么變化的。


2.3 組件棧

支持從多種數據源獲取數據,包括Kafk、Flume、Twitter、ZeroMQ、Kinesis 以及TCP sockets,從數據源獲取數據之后,可以 使用諸如map、reduce、join和window等高級函數進行復雜算法的處理。最后還可以將處理結果 存儲到文件系統,數據庫和現場 儀表盤。在“One Stack rule them all”的基礎上,還可以使用Spark的其他子框架,如集群學習、圖計算等,對流數據進行處 理。


2.4 特性分析


吞吐量與延遲性

Spark目前在EC2上已能夠線性擴展到100個節點(每個節點4Core),可以以數秒的延遲處理6GB/s的數據量(60M records/s),其吞吐量也比流行的Storm高2~5倍,圖4是Berkeley利用WordCount和Grep兩個用例所做的測試,在 Grep這個 測試中,Spark Streaming中的每個節點的吞吐量是670k records/s,而Storm是115k records/s。

Spark Streaming將流式計算分解成多個Spark Job,對于每一段數據的處理都會經過Spark DAG圖分解,以及Spark的任務集的調 度過程,其最小的Batch Size的選取在0.5~2秒鐘之間(Storm目前最小的延遲是100ms左右),所以Spark Streaming能夠滿足 除對實時性要求非常高(如高頻實時交易)之外的所有流式準實時計算場景。


exactly-once 語義

更加穩定的exactly-once語義支持。


反壓能力的支持

Spark Streaming 從v1.5開始引入反壓機制(back-pressure),通過動態控制數據接收速率來適配集群數據處理能力.


Sparkstreaming如何反壓?

簡單來說,反壓機制需要調節系統接受數據速率或處理數據速率,然而系統處理數據的速率是沒法簡單的調節。因此,只能估計當 前系統處理數據的速率,調節系統接受數據的速率來與之相匹配。


Flink如何反壓?

嚴格來說,Flink無需進行反壓,因為系統接收數據的速率和處理數據的速率是自然匹配的。系統接收數據的前提是接收數據的Task 必須有空閑可用的Buffer,該數據被繼續處理的前提是下游Task也有空閑可用的Buffer。因此,不存在系統接受了過多的數據,導 致超過了系統處理的能力。

由此看出,Spark的micro-batch模型導致了它需要單獨引入反壓機制。


反壓與高負載

反壓通常產生于這樣的場景:短時負載高峰導致系統接收數據的速率遠高于它處理數據的速率。

但是,系統能夠承受多高的負載是系統數據處理能力決定的,反壓機制并不是提高系統處理數據的能力,而是系統所面臨負載高于 承受能力時如何調節系統接收數據的速率。


容錯

Driver和executor采用預寫日志(WAL)方式去保存狀態,同時結合RDD本身的血統的容錯機制。


API 和 類庫

Spark 2.0中引入了結構化數據流,統一了SQL和Streaming的API,采用DataFrame作為統一入口,能夠像編寫普通Batch程序或 者直接像操作SQL一樣操作Streaming,易于編程。

廣泛集成


除了可以讀取HDFS, Flume, Kafka, Twitter andZeroMQ數據源以外,我們自己也可以定義數據源,支持運行在Yarn, Standalone及EC2上,能夠通過Zookeeper,HDFS保證高可用性,處理結果可以直接寫到HDFS

部署性

依賴java環境,只要應用能夠加載到spark相關的jar包即可。


3.Storm架構及特性分析

3.1 基本架構


Storm集群采用主從架構方式,主節點是Nimbus,從節點是Supervisor,有關調度相關的信息存儲到ZooKeeper集群中。架構如下:



Nimbus

Storm集群的Master節點,負責分發用戶代碼,指派給具體的Supervisor節點上的Worker節點,去運行Topology對應的組件 (Spout/Bolt)的Task。


Supervisor

Storm集群的從節點,負責管理運行在Supervisor節點上的每一個Worker進程的啟動和終止。通過Storm的配置文件中的 supervisor.slots.ports配置項,可以指定在一個Supervisor上最大允許多少個Slot,每個Slot通過端口號來唯一標識,一個端口號 對應一個Worker進程(如果該Worker進程被啟動)。


ZooKeeper

用來協調Nimbus和Supervisor,如果Supervisor因故障出現問題而無法運行Topology,Nimbus會第一時間感知到,并重新分配 Topology到其它可用的Supervisor上運行。


運行架構

運行流程


1)戶端提交拓撲到nimbus。

2) Nimbus針對該拓撲建立本地的目錄根據topology的配置計算task,分配task,在zookeeper上建立assignments節點存儲 task和supervisor機器節點中woker的對應關系;

在zookeeper上創建taskbeats節點來監控task的心跳;啟動topology。

3) Supervisor去zookeeper上獲取分配的tasks,啟動多個woker進行,每個woker生成task,一個task一個線程;根據topology 信息初始化建立task之間的連接;Task和Task之間是通過zeroMQ管理的;后整個拓撲運行起來。

3.2 基于Yarn層面的架構

在YARN上開發一個應用程序,通常只需要開發兩個組件,分別是客戶端和ApplicationMaster,其中客戶端主要作用是提交應用程 序到YARN上,并和YARN和ApplicationMaster進行交互,完成用戶發送的一些指令;而ApplicationMaster則負責向YARN申請 資源,并與NodeManager通信,啟動任務。


不修改任何Storm源代碼即可將其運行在YARN之上,最簡單的實現方法是將Storm的各個服務組件(包括Nimbus和Supervisor) 作為單獨的任務運行在YARN上,而Zookeeper作為一個公共的服務運行在YARN集群之外的幾個節點上。


1)通過YARN-Storm Client將Storm Application提交到YARN的RM上;

2)RM為YARN-Storm ApplicationMaster申請資源,并將其運行在一個節點上(Nimbus);

3)YARN-Storm ApplicationMaster 在自己內部啟動Nimbus和UI服務;

4)YARN-Storm ApplicationMaster 根據用戶配置向RM申請資源,并在申請到的Container中啟動Supervisor服務;


3.3 組件棧


3.4 特性分析


簡單的編程模型。

類似于MapReduce降低了并行批處理復雜性,Storm降低了進行實時處理的復雜性。


服務化

一個服務框架,支持熱部署,即時上線或下線App.


可以使用各種編程語言

你可以在Storm之上使用各種編程語言。默認支持Clojure、Java、Ruby和Python。要增加對其他語言的支持,只需實現一個簡單 的Storm通信協議即可。


容錯性

Storm會管理工作進程和節點的故障。


水平擴展

計算是在多個線程、進程和服務器之間并行進行的。

可靠的消息處理

Storm保證每個消息至少能得到一次完整處理。任務失敗時,它會負責從消息源重試消息。


快速

系統的設計保證了消息能得到快速的處理,使用ZeroMQ作為其底層消息隊列。


本地模式

Storm有一個“本地模式”,可以在處理過程中完全模擬Storm集群。這讓你可以快速進行開發和單元測試。


部署性

依賴于Zookeeper進行任務狀態的維護,必須首先部署Zookeeper。

4.三種框架的對比分析


對比分析

如果對延遲要求不高的情況下,建議使用Spark Streaming,豐富的高級API,使用簡單,天然對接Spark生態棧中的其他組 件,吞吐量大,部署簡單,UI界面也做的更加智能,社區活躍度較高,有問題響應速度也是比較快的,比較適合做流式的ETL,而 且Spark的發展勢頭也是有目共睹的,相信未來性能和功能將會更加完善。


如果對延遲性要求比較高的話,建議可以嘗試下Flink,Flink是目前發展比較火的一個流系統,采用原生的流處理系統,保證了低延遲性,在API和容錯性上也是做的比較完善,使用起來相對來說也是比較簡單的,部署容易,而且發展勢頭也越來越好,相信后面社區問題的響應速度應該也是比較快的。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容