flink運行架構

任務提交流程(yarn模式)

在這裏插入圖片描述
Flink任務提交後,Client向HDFS上傳Flink的Jar包和配置,之後向Yarn ResourceManager提交任務,ResourceManager分配Container資源並通知對應的NodeManager啓動ApplicationMaster,ApplicationMaster啓動後加載Flink的Jar包和配置構建環境,然後啓動JobManager,之後ApplicationMaster向ResourceManager申請資源啓動TaskManager,ResourceManager分配Container資源後,由ApplicationMaster通知資源所在節點的NodeManager啓動TaskManager,NodeManager加載Flink的Jar包和配置構建環境並啓動TaskManager,TaskManager啓動後向JobManager發送心跳包,並等待JobManager向其分配任務。

任務調度原理

在這裏插入圖片描述
1.客戶端不是運行時和程序執行的一部分,但它用於準備併發送dataflow(JobGraph)給Master(JobManager),然後,客戶端斷開連接或者維持連接以等待接收計算結果。
2.當 Flink 集羣啓動後,首先會啓動一個 JobManger 和一個或多個的 TaskManager。由 Client 提交任務給 JobManager,JobManager 再調度任務到各個 TaskManager 去執行,然後 TaskManager 將心跳和統計信息彙報給 JobManager。TaskManager 之間以流的形式進行數據的傳輸。上述三者均爲獨立的 JVM 進程。
3.Client 爲提交 Job 的客戶端,可以是運行在任何機器上(與 JobManager 環境連通即可)。提交 Job 後,Client 可以結束進程(Streaming的任務),也可以不結束並等待結果返回。
4.JobManager 主要負責調度 Job 並協調 Task 做 checkpoint,職責上很像 Storm 的 Nimbus。從 Client 處接收到 Job 和 JAR 包等資源後,會生成優化後的執行計劃,並以 Task 的單元調度到各個 TaskManager 去執行。
5.TaskManager 在啓動的時候就設置好了槽位數(Slot),每個 slot 能啓動一個 Task,Task 爲線程。從 JobManager 處接收需要部署的 Task,部署啓動後,與自己的上游建立 Netty 連接,接收數據並處理。

執行圖

Flink 中的執行圖可以分成四層:StreamGraph -> JobGraph -> ExecutionGraph -> 物理執行圖。
StreamGraph:是根據用戶通過 Stream API 編寫的代碼生成的最初的圖。用來表示程序的拓撲結構。
JobGraph:StreamGraph經過優化後生成了 JobGraph,提交給 JobManager 的數據結構。主要的優化爲,將多個符合條件的節點 chain 在一起作爲一個節點,這樣可以減少數據在節點之間流動所需要的序列化/反序列化/傳輸消耗。
ExecutionGraph:JobManager 根據 JobGraph 生成ExecutionGraph。ExecutionGraph是JobGraph的並行化版本,是調度層最核心的數據結構。
物理執行圖:JobManager 根據 ExecutionGraph 對 Job 進行調度後,在各個TaskManager 上部署 Task 後形成的“圖”,並不是一個具體的數據結構。
在這裏插入圖片描述

Worker與Slots

每一個worker(TaskManager)是一個JVM進程,它可能會在獨立的線程上執行一個或多個subtask。爲了控制一個worker能接收多少個task,worker通過task slot來進行控制(一個worker至少有一個task slot)。·
每個task slot表示TaskManager擁有資源的一個固定大小的子集。假如一個TaskManager有三個slot,那麼它會將其管理的內存分成三份給各個slot。資源slot化意味着一個subtask將不需要跟來自其他job的subtask競爭被管理的內存,取而代之的是它將擁有一定數量的內存儲備。需要注意的是,這裏不會涉及到CPU的隔離,slot目前僅僅用來隔離task的受管理的內存。
通過調整task slot的數量,允許用戶定義subtask之間如何互相隔離。如果一個TaskManager一個slot,那將意味着每個task group運行在獨立的JVM中(該JVM可能是通過一個特定的容器啓動的),而一個TaskManager多個slot意味着更多的subtask可以共享同一個JVM。而在同一個JVM進程中的task將共享TCP連接(基於多路複用)和心跳消息。它們也可能共享數據集和數據結構,因此這減少了每個task的負載。
在這裏插入圖片描述
Task Slot是靜態的概念,是指TaskManager具有的併發執行能力,可以通過參數taskmanager.numberOfTaskSlots進行配置,而並行度parallelism是動態概念,即TaskManager運行程序時實際使用的併發能力,可以通過參數parallelism.default進行配置。
也就是說,假設一共有3個TaskManager,每一個TaskManager中的分配3個TaskSlot,也就是每個TaskManager可以接收3個task,一共9個TaskSlot,如果設置parallelism.default=1,即運行程序默認的並行度爲1,9個TaskSlot只用了1個,有8個空閒,因此,設置合適的並行度才能提高效率。
在這裏插入圖片描述
在這裏插入圖片描述

並行數據流

Flink程序的執行具有並行、分佈式的特性。在執行過程中,一個 stream 包含一個或多個 stream partition ,而每一個 operator 包含一個或多個 operator subtask,這些operator subtasks在不同的線程、不同的物理機或不同的容器中彼此互不依賴得執行。
一個特定operator的subtask的個數被稱之爲其parallelism(並行度)。一個stream的並行度總是等同於其producing operator的並行度。一個程序中,不同的operator可能具有不同的並行度。
在這裏插入圖片描述
Stream在operator之間傳輸數據的形式可以是one-to-one(forwarding)的模式也可以是redistributing的模式,具體是哪一種形式,取決於operator的種類。
One-to-one:stream(比如在source和map operator之間)維護着分區以及元素的順序。那意味着map operator的subtask看到的元素的個數以及順序跟source operator的subtask生產的元素的個數、順序相同,map、fliter、flatMap等算子都是one-to-one的對應關係。
類似於spark中的窄依賴
Redistributing:stream(map()跟keyBy/window之間或者keyBy/window跟sink之間)的分區會發生改變。每一個operator subtask依據所選擇的transformation發送數據到不同的目標subtask。例如,keyBy() 基於hashCode重分區、broadcast和rebalance會隨機重新分區,這些算子都會引起redistribute過程,而redistribute過程就類似於Spark中的shuffle過程。
類似於spark中的寬依賴

task與operator chains

相同並行度的one to one操作,Flink這樣相連的operator 鏈接在一起形成一個task,原來的operator成爲裏面的subtask。將operators鏈接成task是非常有效的優化:它能減少線程之間的切換和基於緩存區的數據交換,在減少時延的同時提升吞吐量。鏈接的行爲可以在編程API中進行指定。
在這裏插入圖片描述
1.OperatorChain的優點
減少線程切換
減少序列化與反序列化
減少延遲並且提高吞吐能力
2.OperatorChain 組成條件(重要)
上下游算子並行度一致
上下游算子之間沒有數據shuffle

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章