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都分配一個緩沖區。下圖展示了此架構:

在上圖中,有四個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的方式連接:

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

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

任務鏈默認是開啟的。在“控制任務鏈”一節,我們會介紹如何為某個任務關閉任務鏈化,以及如何控制單個operator的鏈行為。
References:
Vasiliki Kalavri, Fabian Hueske. Stream Processing With Apache Flink. 2019
