flink的整個數據處理流程是由一個個operator組成的,數據從源頭開始傳遞給一個個operator進行鏈式處理,每一個處理邏輯就是一個operator,一個operator包含一個輸入、一個處理邏輯、一個輸出,operator是在TaskManager的slot中執行的,一個slot就是一個線程,一個operator只能在一個slot中執行,一個slot中可以運行多個operator(同一個job任務),flink會進行優化將多個operator放在一個slot中運行,它能減少線程之間的切換,減少消息的序列化/反序列化,減少數據在緩衝區的交換,減少了延遲的同時提高整體的吞吐量。根據我們之前給出的示例,我們來看看都有哪些operator,
source operator
DataStreamSource<String> text = env.socketTextStream("localhost", port, "\n")
transform operator
// 計算數據
DataStream<WordWithCount> windowCount = text.flatMap(new FlatMapFunction<String, WordWithCount>() {
public void flatMap(String value, Collector<WordWithCount> out) throws Exception {
String[] splits = value.split(" ");
for (String word : splits) {
out.collect(new WordWithCount(word, 1L));
}
}
})// 打平操作,把每行的單詞轉爲<word,count>類型的數據
.keyBy("word")// 針對相同的word數據進行分組
.timeWindow(Time.seconds(8), Time.seconds(1))// 指定計算數據的窗口大小和滑動窗口大小
.sum("count");
sink operator
// 把數據打印到控制檯
windowCount.print();
flink的執行流程總是以source operator開頭,sink operator結尾,中間夾雜一些transform operator。
下面是運行邏輯圖:
這個示例中flink將source、flatmap、window、sum、sink合併成一個chain放在同一個slot中運行(如果這裏的並行度不一樣,那麼就不會放在一個chain中,具體例子可以看下面的參考文檔),那麼什麼條件下slot會組合成一個chain呢?
1、上下游的並行度一致
2、下游節點的入度爲1 (也就是說下游節點沒有來自其他節點的輸入)
3、上下游節點都在同一個 slot group 中(下面會解釋 slot group)
4、下游節點的 chain 策略爲 ALWAYS(可以與上下游鏈接,map、flatmap、filter等默認是ALWAYS)
5、上游節點的 chain 策略爲 ALWAYS 或 HEAD(只能與下游鏈接,不能與上游鏈接,Source默認是HEAD)
6、兩個節點間數據分區方式是 forward(一對一,沒有shuffle)
7、用戶沒有禁用 chain
多個operator可以組成一個chain,可以作爲一個新的operator,不同的operator可以運行在同一個slot中。