一張圖輕鬆掌握 Flink on YARN 應用啟動全流程(上)

大濤學長發表於2019-09-25
Flink 支援 Standalone 獨立部署和 YARN、Kubernetes、Mesos 等叢集部署模式,其中 YARN 叢集部署模式在國內的應用越來越廣泛。Flink 社群將推出 Flink on YARN 應用解讀系列文章,分為上、下兩篇。本文基於 FLIP-6 重構後的資源排程模型將介紹 Flink on YARN 應用啟動全流程,並進行詳細步驟解析。下篇將根據社群大群反饋,解答客戶端和Flink Cluster的常見問題,分享相關問題的排查思路。

Flink on YARN 流程圖

Flink on YARN叢集部署模式涉及YARN和Flink兩大開源框架,應用啟動流程的很多環節交織在一起,為了便於大家理解,在一張圖上畫出了Flink on YARN基礎架構和應用啟動全流程,並對關鍵角色和流程進行了介紹說明,整個啟動流程又被劃分成客戶端提交(流程標註為紫色)、Flink Cluster啟動和Job提交執行(流程標註為橙色)兩個階段分別闡述,由於分支和細節太多,本文會忽略掉一些,只介紹關鍵流程(基於Flink開源1.9版本原始碼整理)。

一張圖輕鬆掌握 Flink on YARN 應用啟動全流程(上)

客戶端提交流程

1.執行命令:bin/flink run -d -m yarn-cluster ...或bin/yarn-session.sh ...來提交per-job執行模式或session執行模式的應用;
2.解析命令引數項並初始化,啟動指定執行模式,如果是per-job執行模式將根據命令列引數指定的Job主類建立job graph;
  • 如果可以從命令列引數(-yid )或YARN properties臨時檔案(${java.io.tmpdir}/.yarn-properties-${user.name})中獲取應用ID,向指定的應用提交Job;
  • 否則當命令列引數中包含 -d(表示detached模式)和 -m yarn-cluster(表示指定YARN叢集模式),啟動per-job執行模式;
  • 否則當命令列引數項不包含 -yq(表示查詢YARN叢集可用資源)時,啟動session執行模式;
3.獲取YARN叢集資訊、新應用ID並啟動執行前檢查;
  • 透過YarnClient向YARN ResourceManager(下文縮寫為:YARN RM,YARN Master節點,負責整個叢集資源的管理和排程) 請求建立一個新應用(YARN RM收到建立應用請求後生成新應用ID和container申請的資源上限後返回),並且獲取YARN Slave節點報告(YARN RM返回全部slave節點的ID、狀態、rack、http地址、總資源、已使用資源等資訊);
  • 執行前檢查:(1) 簡單驗證YARN叢集能否訪問;(2) 最大node資源能否滿足flink JobManager/TaskManager vcores資源申請需求;(3) 指定queue是否存在(不存在也只是列印WARN資訊,後續向YARN提交時排除異常並退出);(4)當預期應用申請的Container資源會超出YARN資源限制時丟擲異常並退出;(5) 當預期應用申請不能被滿足時(例如總資源超出YARN叢集可用資源總量、Container申請資源超出NM可用資源最大值等)提供一些參考資訊。
4. 將應用配置(flink-conf.yaml、logback.xml、log4j.properties)和相關檔案(flink jars、ship files、user jars、job graph等)上傳至分散式儲存(例如HDFS)的應用暫存目錄(/user/${user.name}/.flink/);
5. 準備應用提交上下文(ApplicationSubmissionContext,包括應用的名稱、型別、佇列、標籤等資訊和應用Master的container的環境變數、classpath、資源大小等),註冊處理部署失敗的shutdown hook(清理應用對應的HDFS目錄),然後透過YarnClient向YARN RM提交應用;
6. 迴圈等待直到應用狀態為RUNNING,包含兩個階段:
  • 迴圈等待應用提交成功(SUBMITTED):預設每隔200ms透過YarnClient獲取應用報告,如果應用狀態不是NEW和NEW_SAVING則認為提交成功並退出迴圈,每迴圈10次會將當前的應用狀態輸出至日誌:"Application submission is not finished, submitted application is still in ",提交成功後輸出日誌:"Submitted application "
  • 迴圈等待應用正常執行(RUNNING):每隔250ms透過YarnClient獲取應用報告,每輪迴圈也會將當前的應用狀態輸出至日誌:"Deploying cluster, current state "。應用狀態成功變為RUNNING後將輸出日誌"YARN application has been deployed successfully." 並退出迴圈,如果等到的是非預期狀態如FAILED/FINISHED/KILLED,就會在輸出YARN返回的診斷資訊("The YARN application unexpectedly switched to state during deployment. Diagnostics from YARN: ...")之後丟擲異常並退出。

Flink Cluster啟動流程

1.YARN RM中的ClientRMService(為普通使用者提供的RPC服務元件,處理來自客戶端的各種RPC請求,比如查詢YARN叢集資訊,提交、終止應用等) 接收到應用提交請求,簡單校驗後將請求轉交給RMAppManager(YARN RM內部管理應用生命週期的元件);
2.RMAppManager根據應用提交上下文內容建立初始狀態為NEW的應用,將應用狀態持久化到RM狀態儲存服務(例如ZooKeeper叢集,RM狀態儲存服務用來保證RM重啟、HA切換或發生故障後叢集應用能夠正常恢復,後續流程中的涉及狀態儲存時不再贅述),應用狀態變為NEW_SAVING;
3.應用狀態儲存完成後,應用狀態變為SUBMITTED;RMAppManager開始向ResourceScheduler(YARN RM可拔插資源排程器,YARN自帶三種排程器FifoScheduler/FairScheduler/CapacityScheduler,其中CapacityScheduler支援功能最多使用最廣泛,FifoScheduler功能最簡單基本不可用,今年社群已明確不再繼續支援FairScheduler,建議已有使用者遷至CapacityScheduler)提交應用,如果無法正常提交(例如佇列不存在、不是葉子佇列、佇列已停用、超出佇列最大應用數限制等)則丟擲拒絕該應用,應用狀態先變為FINAL_SAVING觸發應用狀態儲存流程並在完成後變為FAILED;如果提交成功,應用狀態變為ACCEPTED;
4.開始建立應用執行例項(ApplicationAttempt,由於一次執行例項中最重要的元件是ApplicationMaster,下文簡稱AM,它的狀態代表了ApplicationAttempt的當前狀態,所以ApplicationAttempt實際也代表了AM),初始狀態為NEW;
5.初始化應用執行例項資訊,並向ApplicationMasterService(AM&RM協議介面服務,處理來自AM的請求,主要包括註冊和心跳)註冊,應用例項狀態變為SUBMITTED;
6.RMAppManager維護的應用例項開始初始化AM資源申請資訊並重新校驗佇列,然後向ResourceScheduler申請AM Container(Container是YARN中資源的抽象,包含了記憶體、CPU等多維度資源),應用例項狀態變為ACCEPTED;
7.ResourceScheduler會根據優先順序(佇列/應用/請求每個維度都有優先順序配置) 從根佇列開始層層遞進,先後選擇當前優先順序最高的子佇列、應用直至具體某個請求,然後結合叢集資源分佈等情況作出分配決策,AM Container分配成功後,應用例項狀態變為ALLOCATED_SAVING,並觸發應用例項狀態儲存流程,儲存成功後應用例項狀態變為ALLOCATED;
8.RMAppManager維護的應用例項開始通知ApplicationMasterLauncher(AM生命週期管理服務,負責啟動或清理AM container)啟動AM container,ApplicationMasterLauncher與YARN NodeManager(下文簡稱YARN NM,與YARN RM保持通訊,負責管理單個節點上的全部資源、Container生命週期、附屬服務等,監控節點健康狀況和Container資源使用)建立通訊並請求啟動AM container;
9.ContainerManager(YARN NM核心元件,管理所有Container的生命週期) 接收到AM container啟動請求,YARN NM開始校驗Container Token及資原始檔,建立應用例項和Container例項並儲存至本地,結果返回後應用例項狀態變為LAUNCHED;
10.ResourceLocalizationService(資源本地化服務,負責Container所需資源的本地化。它能夠按照描述從HDFS上下載Container所需的檔案資源,並儘量將它們分攤到各個磁碟上以防止出現訪問熱點) 初始化各種服務元件、建立工作目錄、從HDFS下載執行所需的各種資源至Container工作目錄(路徑為: ${yarn.nodemanager.local-dirs}/usercache/${user}/appcache//);
11.ContainersLauncher(負責container的具體操作,包括啟動、重啟、恢復和清理等) 將待執行Container所需的環境變數和執行命令寫到Container工作目錄下的launch_container.sh指令碼中,然後執行該指令碼啟動Container;
12.Container程式載入並執行ClusterEntrypoint(Flink JobManager入口類,每種叢集部署模式和應用執行模式都有相應的實現,例如在YARN叢集部署模式下,per-job應用執行模式實現類是YarnJobClusterEntrypoint,session應用執行模式實現類是YarnSessionClusterEntrypoint),首先初始化相關執行環境:
  • 輸出各軟體版本及執行環境資訊、命令列引數項、classpath等資訊;
  • 註冊處理各種SIGNAL的handler:記錄到日誌
  • 註冊JVM關閉保障的shutdown hook:避免JVM退出時被其他shutdown hook阻塞
  • 列印YARN執行環境資訊:使用者名稱
  • 從執行目錄中載入flink conf
  • 初始化檔案系統
  • 建立並啟動各類內部服務(包括RpcService、HAService、BlobServer、HeartbeatServices、MetricRegistry、ExecutionGraphStore等)
  • 將RPC address和port更新到flink conf配置
13.啟動ResourceManager(Flink資源管理核心元件,包含YarnResourceManager和SlotManager兩個子元件,YarnResourceManager負責外部資源管理,與YARN RM建立通訊並保持心跳,申請或釋放TaskManager資源,登出應用等;SlotManager則負責內部資源管理,維護全部Slot資訊和狀態)及相關服務,建立非同步AMRMClient,開始註冊AM,註冊成功後每隔一段時間(心跳間隔配置項:${yarn.heartbeat.interval},預設5s)向YARN RM傳送心跳來傳送資源更新請求和接受資源變更結果。YARN RM內部該應用和應用執行例項的狀態都變為RUNNING,並通知AMLivelinessMonitor服務監控AM是否存活狀態,當心跳超過一定時間(預設10分鐘)觸發AM failover流程;
14.啟動Dispatcher(負責接收使用者提供的作業,並且負責為這個新提交的作業拉起一個新的 JobManager)及相關服務(包括REST endpoint等),在per-job執行模式下,Dispatcher將直接從Container工作目錄載入JobGrap檔案;在session執行模式下,Dispatcher將在接收客戶端提交的Job(_透過BlockServer接收job grap檔案)後再進行後續流程;
15.根據JobGraph啟動JobManager(負責作業排程、管理Job和Task的生命週期),構建ExecutionGraph(JobGraph的並行化版本,排程層最核心的資料結構);
16.JobManager開始執行ExecutionGraph,向ResourceManager申請資源;
17.ResourceManager將資源請求加入等待請求佇列,並透過心跳向YARN RM申請新的Container資源來啟動TaskManager程式;後續流程如果有空閒Slot資源,SlotManager將其分配給等待請求佇列中匹配的請求,不用再透過18. YarnResourceManager申請新的TaskManager;
**18.YARN ApplicationMasterService接收到資源請求後,解析出新的資源請求並更新應用請求資訊; **
19.YARN ResourceScheduler成功為該應用分配資源後更新應用資訊,ApplicationMasterService接收到Flink JobManager的下一次心跳時返回新分配資源資訊;
20.Flink ResourceManager接收到新分配的Container資源後,準備好TaskManager啟動上下文(ContainerLauncherContext,生成TaskManager配置並上傳至分散式儲存,配置其他依賴和環境變數等),然後向YARN NM申請啟動TaskManager程式,YARN NM啟動Container的流程與AM Container啟動流程基本類似,區別在於應用例項在NM上已存在並未RUNNING狀態時則跳過應用例項初始化流程,這裡不再贅述;
21.TaskManager程式載入並執行YarnTaskExecutorRunner(Flink TaskManager入口類),初始化流程完成後啟動TaskExecutor(負責執行Task相關操作);
22.TaskExecutor啟動後先向ResourceManager註冊,成功後再向SlotManager彙報自己的Slot資源與狀態; SlotManager接收到Slot空閒資源後主動觸發Slot分配,從等待請求佇列中選出合適的資源請求後,向 TaskManager請求該Slot資源
23.TaskManager收到請求後檢查該Slot是否可分配(不存在則返回異常資訊)、Job是否已註冊(沒有則先註冊再分配Slot),檢查透過後將Slot分配給JobManager;
24.JobManager檢查Slot分配是否重複,透過後通知Execution執行部署task流程,向TaskExecutor提交task; TaskExecutor啟動新的執行緒執行Task。
本文作者:巴蜀真人
本文為雲棲社群原創內容,未經允許不得轉載。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69947441/viewspace-2658222/,如需轉載,請註明出處,否則將追究法律責任。

相關文章