Flink-運行時架構中的四大組件|任務提交流程|任務調度原理|Slots和並行度中間的關係|數據流|執行圖|數據得傳輸形式|任務鏈

Flink運行時架構主要包括四個不同的組件,它們會在運行流處理應用程序時協同工作:作業管理器(JobManager)、資源管理器(ResourceManager)、任務管理器(TaskManager),以及分發器(Dispatcher)。因爲Flink是用Java和Scala實現的,所以所有組件都會運行在Java虛擬機上。每個組件的職責如下:

作業管理器(JobManager)

  1. 控制一個應用程序執行的主進程,也就是說,每個應用程序都會被一個不同的JobManager 所控制執行。
  2. JobManager 會先接收到要執行的應用程序,這個應用程序會包括:作業圖(JobGraph)、邏輯數據流圖(logical dataflow graph)和打包了所有的類、庫和其它資源的JAR包。
  3. JobManager 會把JobGraph轉換成一個物理層面的數據流圖,這個圖被叫做“執行圖”(ExecutionGraph),包含了所有可以併發執行的任務。
  4. JobManager 會向資源管理器(ResourceManager)請求執行任務必要的資源,也就是任務管理器(TaskManager)上的插槽(slot)。一旦它獲取到了足夠的資源,就會將執行圖分發到真正運行它們的TaskManager上。而在運行過程中,JobManager會負責所有需要中央協調的操作,比如說檢查點(checkpoints)的協調。

任務管理器(TaskManager)

  1. Flink中的工作進程。通常在Flink中會有多個TaskManager運行,每一個TaskManager都包含了一定數量的插槽(slots)。插槽的數量限制了TaskManager能夠執行的任務數量。
  2. 啓動之後,TaskManager會向資源管理器註冊它的插槽;收到資源管理器的指令後,TaskManager就會將一個或者多個插槽提供給JobManager調用。JobManager就可以向插槽分配任務(tasks)來執行了。
  3. 在執行過程中,一個TaskManager可以跟其它運行同一應用程序的TaskManager交換數據。

資源管理器(ResourceManager)

  1. 主要負責管理任務管理器(TaskManager)的插槽(slot),TaskManger 插槽是Flink中定義的處理資源單元。
  2. Flink爲不同的環境和資源管理工具提供了不同資源管理器,比如YARN、Mesos、K8s,以及standalone部署。
  3. 當JobManager申請插槽資源時,ResourceManager會將有空閒插槽的TaskManager分配給JobManager。如果ResourceManager沒有足夠的插槽來滿足JobManager的請求,它還可以向資源提供平臺發起會話,以提供啓動TaskManager進程的容器。

分發器(Dispatcher)

  1. 可以跨作業運行,它爲應用提交提供了REST接口。
  2. 當一個應用被提交執行時,分發器就會啓動並將應用移交給一個JobManager。
  3. Dispatcher也會啓動一個Web UI,用來方便地展示和監控作業執行的信息。
  4. Dispatcher在架構中可能並不是必需的,這取決於應用提交運行的方式。

任務提交流程

這是從一個較爲高層級的視角,來看應用中各組件的交互協作。如果部署的集羣環境不同(例如YARN,Mesos,Kubernetes,standalone等),其中一些步驟可以被省略,或是有些組件會運行在同一個JVM進程中。

在這裏插入圖片描述

Yarn模式任務提交流程

  1. Flink任務提交後,Client向HDFS上傳Flink的Jar包和配置
  2. 之後客戶端向Yarn ResourceManager提交任務,ResourceManager分配Container資源並通知對應的NodeManager啓動ApplicationMaster
  3. ApplicationMaster啓動後加載Flink的Jar包和配置構建環境,去啓動JobManager,之後JobManager向Flink自身的RM進行申請資源,自身的RM向Yarn 的ResourceManager申請資源(因爲是yarn模式,所有資源歸yarn RM管理)啓動TaskManager
  4. Yarn ResourceManager分配Container資源後,由ApplicationMaster通知資源所在節點的NodeManager啓動TaskManager
  5. NodeManager加載Flink的Jar包和配置構建環境並啓動TaskManager,TaskManager啓動後向JobManager發送心跳包,並等待JobManager向其分配任務。

在這裏插入圖片描述

任務調度原理

  1. 客戶端不是運行時和程序執行的一部分,但它用於準備併發送dataflow(JobGraph)給Master(JobManager),然後,客戶端斷開連接或者維持連接以等待接收計算結果。而Job Manager會產生一個執行圖(Dataflow Graph)
  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 連接,接收數據並處理。

在這裏插入圖片描述

TaskManger與Slots與parallelism

  1. Flink 中每一個 TaskManager 都是一個JVM進程,它可能會在獨立的線程上執行一個或多個子任務
  2. 爲了控制一個 TaskManager 能接收多少個 task, TaskManager 通過 task slot 來進行控制(一個 TaskManager 至少有一個 slot)
  3. 圖中每個Task Manager中的Slot爲3個,那麼兩個Task Manager一共有六個Slot, 而這6個Slot代表着Task Manager最大的併發執行能力,一共能可以執行6個task進行同時執行
  4. Slot是靜態概念,代表着Task Manager具有的併發執行能力,可以通過參數taskmanager.numberOfTaskSlots進行配置
  5. 爲了控制一個 TaskManager 能接收多少個 task, TaskManager 通過 task slot 來進行控制(一個 TaskManager 至少有一個 slot)
  6. 圖中Source和Map是一個Task,且並行度(我們設置的setParallelism())都爲1,指這個task任務的並行能力爲1,只佔用一個Slot資源

在這裏插入圖片描述
7. 在第二張圖中爲Flink的共享子任務,如果一個TaskManager一個slot,那將意味着每個task group運行在獨立的JVM中(該JVM可能是通過一個特定的容器啓動的),而一個TaskManager多個slot意味着更多的subtask可以共享同一個JVM。而在同一個JVM進程中的task將共享TCP連接(基於多路複用)和心跳消息。它們也可能共享數據集和數據結構,因此這減少了每個task的負載。
8. 並行度parallelism是動態概念,即TaskManager運行程序時實際使用的併發能力,可以通過參數parallelism.default進行配置。
在這裏插入圖片描述

  1. 也就是說,假設一共有3個TaskManager,每一個TaskManager中的分配3個TaskSlot,也就是每個TaskManager可以接收3個task,一共9個TaskSlot,如果我們設置parallelism.default=1,即運行程序默認的並行度爲1,9個TaskSlot只用了1個,有8個空閒,因此,設置合適的並行度才能提高效率。

在這裏插入圖片描述
在這裏插入圖片描述

  1. 一個特定算子的 子任務(subtask)的個數被稱之爲其並行度(parallelism),我們可以對單獨的每個算子進行設置並行度,也可以直接用env設置全局的並行度,更可以在頁面中去指定並行度。
  2. 最後,由於並行度是實際Task Manager處理task 的能力,而一般情況下,一個 stream 的並行度,可以認爲就是其所有算子中最大的並行度,則可以得出在設置Slot時,在所有設置中的最大設置的並行度大小則就是所需要設置的Slot的數量。

在這裏插入圖片描述

程序與數據流

  1. 所有的Flink程序都是由三部分組成的: Source 、Transformation 和 Sink。
  2. Source 負責讀取數據源,Transformation 利用各種算子進行處理加工,Sink 負責輸出

在這裏插入圖片描述

  1. 在運行時,Flink上運行的程序會被映射成“邏輯數據流”(dataflows),它包含了這三部分
  2. 每一個dataflow以一個或多個sources開始以一個或多個sinks結束。dataflow類似於任意的有向無環圖(DAG)
  3. 在大部分情況下,程序中的轉換運算(transformations)跟dataflow中的算子(operator)是一一對應的關係

在這裏插入圖片描述

執行圖

  1. Flink 中的執行圖可以分成四層:StreamGraph -> JobGraph -> ExecutionGraph -> 物理執行圖
  2. StreamGraph:是根據用戶通過 Stream API 編寫的代碼生成的最初的圖。用來表示程序的拓撲結構。
  3. JobGraph:StreamGraph經過優化後生成了 JobGraph,提交給 JobManager 的數據結構。主要的優化爲,將多個符合條件的節點 chain 在一起作爲一個節點
  4. ExecutionGraph:JobManager 根據 JobGraph 生成ExecutionGraph。ExecutionGraph是JobGraph的並行化版本,是調度層最核心的數據結構。
  5. 物理執行圖:JobManager 根據 ExecutionGraph 對 Job 進行調度後,在各個TaskManager 上部署 Task 後形成的“圖”,並不是一個具體的數據結構。

在這裏插入圖片描述

數據傳輸形式

  1. 一個程序中,不同的算子可能具有不同的並行度
  2. 算子之間傳輸數據的形式可以是 one-to-one (forwarding) 的模式也可以是redistributing 的模式,具體是哪一種形式,取決於算子的種類
  3. One-to-one:stream維護着分區以及元素的順序(比如source和map之間)。這意味着map 算子的子任務看到的元素的個數以及順序跟 source 算子的子任務生產的元素的個數、順序相同。map、fliter、flatMap等算子都是one-to-one的對應關係。
  4. Redistributing:stream的分區會發生改變。每一個算子的子任務依據所選擇的transformation發送數據到不同的目標任務。例如,keyBy 基於 hashCode 重分區、而 broadcast 和 rebalance 會隨機重新分區,這些算子都會引起redistribute過程,而 redistribute 過程就類似於 Spark 中的 shuffle 過程。

任務鏈(Operator Chains)

  1. Flink 採用了一種稱爲任務鏈的優化技術,可以在特定條件下減少本地通信的開銷。爲了滿足任務鏈的要求,必須將兩個或多個算子設爲相同的並行度,並通過本地轉發(local forward)的方式進行連接
  2. 相同並行度的 one-to-one 操作,Flink 這樣相連的算子鏈接在一起形成一個 task,原來的算子成爲裏面的 subtask
  3. 並行度相同、並且是 one-to-one 操作,兩個條件缺一不可
  4. 而爲什麼需要並行度相同,因爲若flatMap並行度爲1,到了之後的map並行度爲2,從flatMap到map的數據涉及到數據由於並行度map爲2會往兩個slot處理,數據會分散,所產生的元素個數和順序發生的改變所以有2個單獨的task,不能成爲任務鏈

在這裏插入圖片描述

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