Flink 內(nèi)部是基于producer-consumer模型來(lái)進(jìn)行消息傳遞的,F(xiàn)link的反壓設(shè)計(jì)也是基于這個(gè)模型。
Flink 使用了高效有界的分布式阻塞隊(duì)列,就像 Java 通用的阻塞隊(duì)列(BlockingQueue)一樣。
下游消費(fèi)者消費(fèi)變慢,上游就會(huì)受到阻塞。
- Flink 1.5 之前的版本并沒(méi)有對(duì)反壓做特別的處理,它利用buffer來(lái)暫存堆積的無(wú)法處理的數(shù)據(jù),當(dāng) buffer 用滿了,則上游的流阻塞,不再發(fā)送數(shù)據(jù)??梢?jiàn)此時(shí)的反壓是從下游往上游傳播的,一直往上傳播到 Source Task 后,Source Task最終會(huì)降低或提升從外部Source 端讀取數(shù)據(jù)的速率。
這種機(jī)制有一個(gè)比較大的問(wèn)題,在這樣的一個(gè)場(chǎng)景下:同一 Task的不同 SubTask 被安排到同一個(gè) TaskManager,則SubTask與其他TaskManager 的網(wǎng)絡(luò)連接將被多路復(fù)用并共享一個(gè) TCP信道以減少資源使用,所以某個(gè) SubTask產(chǎn)生了反壓的話會(huì)把多路復(fù)用的TCP通道占住,從而會(huì)把其他復(fù)用同一 TCP信道的且沒(méi)有流量壓力的SubTask阻塞。
- Flink1.5版本之后的基于Credit反壓機(jī)制解決了上述問(wèn)題。
這種機(jī)制主要是每次上游SubTask給下游SubTask發(fā)送數(shù)據(jù)時(shí),會(huì)把Buffer中的數(shù)據(jù)和上游ResultSubPartition堆積的數(shù)據(jù)量Backlog size發(fā)給下游,下游會(huì)接收上游發(fā)來(lái)的數(shù)據(jù),并向上游反饋目前下游現(xiàn)在的Credit值,Credit值表示目前下游可以接收上游的Buffer量,1個(gè)Buffer等價(jià)于1個(gè)Credit。
可見(jiàn),這種策略上游向下游發(fā)送數(shù)據(jù)是按需發(fā)送的,而不是和之前一樣會(huì)在公用的Netty和TCP這一層數(shù)據(jù)堆積,避免了影響其他SubTask通信的問(wèn)題。