天天看點

Flink架構(二)- Flink中的資料傳輸

2. Flink中的資料傳輸

在一個運作的application中,它的tasks在持續交換資料。TaskManager負責做資料傳輸。TaskManager的網絡元件首先從緩沖buffer中收集records,然後再發送。也就是說,records并不是一個接一個的發送,而是先放入緩沖,然後再以batch的形式發送。這個技術可以高效使用網絡資源,并達到高吞吐。類似于網絡或磁盤 I/O 協定中使用的緩沖技術。

這裡需要注意的是:傳輸緩沖buffer中的記錄,隐含表示的是,Flink的處理模型是基于微批處理的。

每個TaskManager有一組網絡緩沖池(預設每個buffer是32KB),用于發送與接受資料。如發送端和接收端位于不同的TaskManager程序中,則它們需要通過作業系統的網絡棧進行交流。流應用需要以管道的模式進行資料交換,也就是說,每對TaskManager會維持一個永久的TCP連接配接用于做資料交換。在shuffle連接配接模式下(多個sender與多個receiver),每個sender task需要向每個receiver task,此時TaskManager需要為每個receiver task都配置設定一個緩沖區。下圖展示了此架構:

Flink架構(二)- Flink中的資料傳輸

在上圖中,有四個sender 任務,對于每個sender,都需要有至少四個network buffer用于向每個receiver發送資料。每個receiver都需要有至少四個buffer用于接收資料。TaskManager之間的buffer以多路複用的方式使用同一網絡連接配接。為了提供平滑的資料管道型的資料交換,一個TaskManager必須能提供足夠的緩沖,以服務所有并行的出入連接配接。對于shuffle或broadcast 連接配接,每個發送任務和每個接受任務之間都需要一個buffer。Flink的預設網絡緩沖配置足夠适用與小型與中型的叢集任務。對于大型的叢集任務,需要對此配置進行調優。

若sender與receiver任務都運作在同一個TaskManager程序,則sender任務會将發送的條目做序列化,并存入一個位元組緩沖。然後将緩沖放入一個隊列,直到隊列被填滿。Receiver任務從隊列中擷取緩沖,并反序列化輸入的條目。是以,在同一個TaskManager内,任務之間的資料傳輸并不經過網絡互動。

Flink采用了不同的技術用于減少tasks之間的溝通成本。在接下來的部分中,我們會讨論基于積分的(credit-based )流控制與任務鍊(task chaining)。

基于積分的(Credit-Based )流控制

通過網絡發送單獨的條目是一個并不高效的方式,并且會造成大量負載。使用緩沖技術可以更好的使用網絡連接配接的帶寬。在流處理場景中,緩沖的一個缺點是:它增加了延時,因為records需要先放入緩沖,而不是被立即傳輸。

Flink實作了一個credit-based 流控制機制,工作方式為:一個接收任務會授權給一個發送任務一些積分(credit),用于控制預留的緩沖區個數。當一個sender接收到了積分通知,它向會receiver發送 buffers(最多不超過被授權的數量)以及它的backlog大小(已經充滿了并等待被發送的buffer數量)。Receiver使用預留的buffer處理接收到的資料,并使用sender的backlog大小作為下一次授權的積分數,提供給所有與它連接配接的senders。

Credit-based 流控制減少了延時,因為senders可以在receiver有足夠的資源接受資料時,盡快向它發送資料。它在Flink中是一個重要的部分,助力Flink達到高吞吐與低延時。

任務鍊(task chaining)

Flink另一個優化技術稱為任務鍊,用于(在某些情況下)減少本地通信的過載。為了滿足任務鍊的條件,至少兩個以上的operator必須配置為同一并行度,并且使用本地向前的(local forwad)方式連接配接。下圖的operator管道即滿足這些條件。它包含3個operators,全部被配置為并行度為2,并且以local-forward的方式連接配接:

Flink架構(二)- Flink中的資料傳輸

下圖描述了管道是如何以任務鍊的方式執行的。Operators的函數被融合成單個任務,并由一個單獨的線程執行。一個function産生的records,通過使用一個簡單的方法調用,被遞交給下一個function。是以,這裡在方法之間的records傳遞中,基本沒有序列化以及通信消耗。

Flink架構(二)- Flink中的資料傳輸

任務鍊可以極大減少本地task之間的通信成本,但是有時候在執行一個管道時,不使用任務鍊也是合理的。例如,将一個包含多個鍊式任務的長管道斷開,或是将一個鍊分成兩個任務,并将較為消耗資源的function排程到另一個slot上。這些都是合理的。下圖描繪了同樣一個執行的管道,但未使用任務鍊。所有function由一個單獨的task,在它自身的線程中運作。

Flink架構(二)- Flink中的資料傳輸

任務鍊預設是開啟的。在“控制任務鍊”一節,我們會介紹如何為某個任務關閉任務鍊化,以及如何控制單個operator的鍊行為。

References:

Vasiliki Kalavri, Fabian Hueske. Stream Processing With Apache Flink. 2019