flink1.10版本StreamGraph生成過程分析

wangwei0721發表於2020-11-21

1、StreamGraph本質
本質就是按照用程式程式碼的執行順序構建出來的用於向執行環境傳輸的流式圖,並且可以支援視覺化展示給使用者的一種資料結構。
2、StreamGraph、StreamNode和StreamEdge的資料結構
StreamGraph構建DAG流圖時,其核心是要維護好節點及節點之間的關係即可,關於這塊主要是以下關鍵屬性:

而節點之間的關係是由節點自身資料結構來維護的,在StreamNode包含著節點和上下游節點間的關係:

節點關係的具體表徵就是StreamEdge了:

以上三個類除了維護構建DAG流圖相關屬性外,還包含了其他與流程式執行相關的屬性以及一些其他引數,如輸入輸出序列化、格式化等等。
3、構建入口

從StreamExecutionEnvironment環境中構建StreamGraph時分成兩個部分:
首先從全域性執行環境引數中構建出一個StreamGraphGenerator物件,並將部分全域性引數設定進去;
然後再由這個StreamGraphGenerator物件去generat出StreamGraph
3、構建過程

構建過程又可以分為兩個步驟:
首先new一個StreamGraph物件,並且設定其全域性的一些config引數:
然後對其中的每一個transform運算元進行迴圈遞迴處理,組織其內部的Node與Edge關係,形成最終結果:
單個運算元的處理時,根據每個運算元的型別有其單獨的演算法

4、Transformation抽象類的體系結構
這裡沒有定義為介面而是一個抽象類,猜測設計這個類的初衷是提取公共屬性而非提取transform的模板方法了,否則也不會有上面那一大坨分類處理的ifelse

5、transform運算元具體邏輯
transform運算元的套路額基本相差不大,都是由transformXXX方法完成,大概都包含以下步驟:
a、包含input時先遞迴處理上游運算元;
b、通過一個hashmap的緩衝池檢驗是否已經處理過,避免重複處理
c、選擇slot共享演算法
d、生成StreamNode並加入StreamGraph
e、設定輸入輸出序列化方式、格式化型別等規則
f、設定運算元並行度
g、生成StreamEdge,維護正確的上下游關係
其中如果有多輸入或者虛擬節點時,根據具體規則進行節點的拆分重組,然後再遞迴呼叫即可,下面看各型別節點的具體處理規則
OneInputTransformation<IN, OUT>

TwoInputTransformation<IN1, IN2, OUT>

SourceTransformation:source節點沒有上游節點了,其邊的關係由他的下游節點維護即可

SinkTransformation

UnionTransformation:union時,只需維護好上下游的關係即可,正確連線起來

SplitTransformation:split則拆分出兩個OutputSelector

SelectTransformation:select當做虛擬運算元處理

FeedbackTransformation:feedback比較特殊,形成新類似的source/sink節點對,需要再次分別處理

CoFeedbackTransformation:對比參考FeedbackTransformation
PartitionTransformation:partition也是作為一類虛擬節點來處理,

SideOutputTransformation:類似partition

6、StreamGraph的addSink、addSource以及addOperator、addEdge方法
在transform各類運算元時,其實在構建流圖時最核心的方法是呼叫了addOperator和addEdge方法;
addSink和addSource其實是呼叫了addOperator,同時儲存了對應的編碼

而addOperator則是呼叫了addNode方法來新增Node,順便再次補充設定輸入輸出的序列化方法和格式化型別

最後來看addNode方法,此處才是真正生成Node並且加入圖的方法

addEdge就比較簡單了,直接呼叫addEdgeInternal方法,在addEdgeInternal方法類進行分類處理,如果是虛擬節點就按照對應規則進行拆分重組然後再遞迴呼叫,如果是普通節點就構建關係銜接起來即可

至此,整個由StreamExecutionEnvironment中生成StreamGraph的全過程,尤其是構建流圖的核心邏輯解析完了
7、最後補充一個點
在StreamExecutionEnvironment中的transforms集合中其實是沒有儲存source運算元的,是由source運算元的下游往前找input時補充回去的,看執行時的程式碼:


對比即可發現,同時在StreamExecutionEnvironment的addSource方法中是沒有新增operator操作的

相關文章