1. 程式人生 > >Flink中的資料傳輸與背壓

Flink中的資料傳輸與背壓

一圖道盡心酸:

大的原理,上游的task產生資料後,會寫在本地的快取中,然後通知JM自己的資料已經好了,JM通知下游的Task去拉取資料,下游的Task然後去上游的Task拉取資料,形成鏈條。

但是在何時通知JM?這裡有一個設定,比如pipeline還是blocking,pipeline意味著上游哪怕產生一個數據,也會去通知,blocking則需要快取的插槽存滿了才會去通知,預設是pipeline。

雖然生產資料的是Task,但是一個TaskManager中的所有Task共享一個NetworkEnvironment,下游的Task利用ResultPartitionManager主動去上游Task拉資料,底層利用的是Netty和TCP實現網路鏈路的傳輸。

那麼,一直都在說Flink的背壓是一種自然的方式,為什麼是自然的了?

從上面的圖中下面的鏈路中可以看到,當下遊的process邏輯比較慢,無法及時處理資料時,他自己的local buffer中的訊息就不能及時被消費,進而導致netty無法把資料放入local buffer,進而netty也不會去socket上讀取新到達的資料,進而在tcp機制中,tcp也不會從上游的socket去讀取新的資料,上游的netty也是一樣的邏輯,它無法傳送資料,也就不能從上游的localbuffer中消費資料,所以上游的localbuffer可能就是滿的,上游的operator或者process在處理資料之後進行collect.out的時候申請不能本地快取,導致上游的process被阻塞。這樣,在這個鏈路上,就實現了背壓。

如果還有相應的上游,則會一直反壓上去,一直影響到source,導致source也放慢從外部訊息源讀取訊息的速度。一旦瓶頸解除,網路鏈路暢通,則背壓也會自然而然的解除。