長久以來,在YARN集群中部署Flink作業有兩種模式,即Session Mode和Per-Job Mode,而在Flink 1.11版本中,又引入了第三種全新的模式:Application Mode。本文先回顧兩種傳統模式的做法與存在的問題,再簡要介紹Application Mode。
傳統部署模式
Session模式
Session模式是預分配資源的,也就是提前根據指定的資源參數初始化一個Flink集群,並常駐在YARN系統中,擁有固定數量的JobManager和TaskManager(注意JobManager只有一個)。提交到這個集群的作業可以直接運行,免去每次分配資源的overhead。但是Session的資源總量有限,多個作業之間又不是隔離的,故可能會造成資源的爭用;如果有一個TaskManager宕機,它上面承載着的所有作業也都會失敗。另外,啟動的作業越多,JobManager的負載也就越大。所以,Session模式一般用來部署那些對延遲非常敏感但運行時長較短的作業。
Per-Job模式
顧名思義,在Per-Job模式下,每個提交到YARN上的作業會各自形成單獨的Flink集群,擁有專屬的JobManager和TaskManager。可見,以Per-Job模式提交作業的啟動延遲可能會較高,但是作業之間的資源完全隔離,一個作業的TaskManager失敗不會影響其他作業的運行,JobManager的負載也是分散開來的,不存在單點問題。當作業運行完成,與它關聯的集群也就被銷毀,資源被釋放。所以,Per-Job模式一般用來部署那些長時間運行的作業。
存在的問題
Deployer代表向YARN集群發起部署請求的節點,一般來講在生產環境中,也總有這樣一個節點作為所有作業的提交入口(即客戶端)。在main()方法開始執行直到env.execute()方法之前,客戶端也需要做一些工作,即:
獲取作業所需的依賴項;
通過執行環境分析並取得邏輯計划,即StreamGraph→JobGraph;
將依賴項和JobGraph上傳到集群中。
只有在這些都完成之后,才會通過env.execute()方法觸發Flink運行時真正地開始執行作業。試想,如果所有用戶都在Deployer上提交作業,較大的依賴會消耗更多的帶寬,而較復雜的作業邏輯翻譯成JobGraph也需要吃掉更多的CPU和內存,客戶端的資源反而會成為瓶頸——不管Session還是Per-Job模式都存在此問題。為了解決它,社區在傳統部署模式的基礎上實現了Application模式。
Application模式
此模式下的作業提交框圖如下。
可見,原本需要客戶端做的三件事被轉移到了JobManager里,也就是說main()方法在集群中執行(入口點位於ApplicationClusterEntryPoint),Deployer只需要負責發起部署請求了。另外,如果一個main()方法中有多個env.execute()/executeAsync()調用,在Application模式下,這些作業會被視為屬於同一個應用,在同一個集群中執行(如果在Per-Job模式下,就會啟動多個集群)。可見,Application模式本質上是Session和Per-Job模式的折衷。
----------------
Session-Cluster模式
Session-Cluster模式需要先啟動集群,然后再提交作業,接着會向yarn申請一塊空間后,資源永遠保持不變。如果資源滿了,下一個作業就無法提交,只能等到yarn中的其中一個作業執行完成后,釋放了資源,下個作業才會正常提交。所有作業共享Dispatcher和ResourceManager;共享資源;適合規模小執行時間短的作業。
Per-Job-Cluster模式
一個任務會對應一個Job,每提交一個作業會根據自身的情況,都會單獨向yarn申請資源,直到作業執行完成,一個作業的失敗與否並不會影響下一個作業的正常提交和運行。獨享Dispatcher和ResourceManager,按需接受資源申請;適合規模大長時間運行的作業。