Flink 支持 Standalone 獨立部署和 YARN、Kubernetes、Mesos 等集羣部署模式,其中 YARN 集羣部署模式在國內的應用愈來愈普遍。Flink 社區將推出 Flink on YARN 應用解讀系列文章,分爲上、下兩篇。上篇分享了基於 FLIP-6 重構後的資源調度模型介紹 Flink on YARN 應用啓動全流程,本文將根據社區大羣反饋,解答客戶端和 Flink Cluster 的常見問題,分享相關問題的排查思路。html
客戶端常見問題與排查思路java
▼ 應用提交控制檯異常信息:Could not build the program from JAR file.node
這個問題的迷惑性較大,不少時候並不是指定運行的 JAR 文件問題,而是提交過程當中發生了異常,須要根據日誌信息進一步排查。最多見緣由是未將依賴的 Hadoop JAR 文件加到 CLASSPATH,找不到依賴類(例如:ClassNotFoundException: org.apache.hadoop.yarn.exceptions.YarnException)致使加載客戶端入口類(FlinkYarnSessionCli)失敗。apache
**▼ Flink on YARN 應用提交時如何關聯到指定 YARN 集羣? **網絡
Flink on YARN 客戶端一般需配置 HADOOP_CONF_DIR 和 HADOOP_CLASSPATH 兩個環境變量來讓客戶端能加載到 Hadoop 配置和依賴 JAR 文件。示例(已有環境變量 HADOOP_HOME 指定 Hadoop 部署目錄):多線程
export HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop export HADOOP_CLASSPATH=`${HADOOP_HOME}/bin/hadoop classpath`app
▼ 客戶端日誌在哪裏,如何配置?框架
客戶端日誌一般在 Flink 部署目錄的 log 文件夾下:${FLINK_HOME}/log/flink-${USER}-client-.log,使用 log4j 配置:${FLINK_HOME}/conf/log4j-cli.properties。異步
有的客戶端環境比較複雜,難以定位日誌位置和配置時,能夠經過如下環境變量配置打開 log4j 的 DEBUG 日誌,跟蹤 log4j 的初始化和詳細加載流程:export JVM_ARGS="-Dlog4j.debug=true"maven
▼ 客戶端疑難問題排查思路
當客戶端日誌沒法正常定位時,能夠修改 log4j 配置文件將日誌級別由 INFO 改成 DEBUG 後從新運行,看是否有 DEBUG 日誌能夠幫助排查問題。對於一些沒有日誌或日誌信息不完整的問題,可能須要開展代碼級調試,修改源碼從新打包替換的方式太過繁瑣,推薦使用 Java 字節碼注入工具 Byteman(詳細語法說明請參考:Byteman Document),使用示例:
(1) 編寫調試腳本,例如打印 Flink 實際使用的 Client 類,如下腳本表示在 CliFrontend#getActiveCustomCommandLine 函數退出時打印其返回值;
RULE test CLASS org.apache.flink.client.cli.CliFrontend METHOD getActiveCustomCommandLine AT EXIT IF TRUE DO traceln("------->CliFrontend#getActiveCustomCommandLine return: "+$!); ENDRULE
(2) 設置環境變量,使用 byteman javaagent:
export BYTEMAN_HOME=/path/to/byte-home export TRACE_SCRIPT=/path/to/script export JVM_ARGS="-javaagent:${BYTEMAN_HOME}/lib/byteman.jar=script:${TRACE_SCRIPT}"
(3) 運行測試命令 bin/flink run -m yarn-cluster -p 1 ./examples/streaming/WordCount.jar ,控制檯將輸出內容:
------->CliFrontend#getActiveCustomCommandLine return: org.apache.flink.yarn.cli.FlinkYarnSessionCli@25ce9dc4
Flink Cluster 常見問題與排查思路
▼ 用戶應用和框架 JAR 包版本衝突問題
該問題一般會拋出 NoSuchMethodError/ClassNotFoundException/IncompatibleClassChangeError 等異常,要解決此類問題:
** 1.首先須要根據異常類定位依賴庫*,而後能夠在項目中執行 mvn dependency:tree 以樹形結構展現所有依賴鏈,再從中定位衝突的依賴庫,也能夠增長參數 -Dincludes 指定要顯示的包,格式爲 [groupId]:[artifactId]:[type]:[version],支持匹配,多個用逗號分隔,例如:mvn dependency:tree -Dincludes=power,javaassist;
2.定位衝突包後就要考慮如何排包,簡單的方案是用 exclusion 來排除掉其從他依賴項目中傳遞過來的依賴,不過有的應用場景須要多版本共存,不一樣組件依賴不一樣版本,就要考慮用 Maven Shade 插件來解決,詳情請參考 Maven Shade Plugin。
▼ 依賴庫有多版本 JAR 包共存時如何肯定某類的具體來源?
不少應用運行 CLASSPATH 中存在相同依賴庫的多個版本 JAR 包,致使實際使用的版本跟加載順序有關,排查問題時常常須要肯定某個類的來源 JAR,Flink 支持給 JM/TM 進程配置 JVM 參數,所以能夠經過下面三個配置項來打印加載類及其來源(輸出在 .out 日誌),根據具體須要選擇其中之一便可:
env.java.opts=-verbose:class //配置JobManager&TaskManager env.java.opts.jobmanager=-verbose:class //配置JobManager env.java.opts.taskmanager=-verbose:class //配置TaskManager
▼ Flink 應用的完整日誌如何查看?
Flink 應用運行中的 JM/TM 日誌能夠在 WebUI 上查看,可是查問題時一般須要結合完整日誌來分析排查,所以就須要瞭解 YARN 的日誌保存機制,YARN 上 Container 日誌保存位置跟應用狀態有關:
1.若是應用尚未結束,Container 日誌會一直保留在其運行所在的節點上,即便 Container 已經運行完成仍然能夠在所在節點的配置目錄下找到: ${yarn.nodemanager.log-dirs}//,也能夠直接從 WebUI訪問:http:///node/containerlogs//
2.若是應用已結束而且集羣啓用了日誌收集(yarn.log-aggregation-enable=true),則一般應用結束後(也有配置能夠增量上傳)NM會將其所有日誌上傳至分佈式存儲(一般是 HDFS)並刪除本地文件,咱們能夠經過 yarn 命令 yarn logs -applicationId -appOwner 查看應用的所有日誌,還能夠增長參數項 -containerId -nodeAddress 來查看某 container 的日誌,也能夠直接訪問分佈式存儲目錄:${yarn.nodemanager.remote-app-log-dir}/${user}/${yarn.nodemanager.remote-app-log-dir-suffix}/
▼ Flink 應用資源分配問題排查思路
若是 Flink 應用不能正常啓動達到 RUNNING 狀態,能夠按如下步驟進行排查:
1.須要先檢查應用當前狀態,根據上述對啓動流程的說明,咱們知道:
-
處於 NEW_SAVING 狀態時正在進行應用信息持久化,若是持續處於這個狀態咱們須要檢查 RM 狀態存儲服務(一般是 ZooKeeper 集羣)是否正常;
-
若是處於 SUBMITTED 狀態,多是 RM 內部發生一些 hold 讀寫鎖的耗時操做致使事件堆積,須要根據 YARN 集羣日誌進一步定位;
-
若是處於 ACCEPTED 狀態,須要先檢查 AM 是否正常,跳轉到步驟2;
-
若是已是 RUNNING 狀態,可是資源沒有所有拿到致使 JOB 沒法正常運行,跳轉到步驟 3;
2.檢查 AM 是否正常,能夠從 YARN 應用展現界面(http:///cluster/app/)或 YARN 應用 REST API(http:///ws/v1/cluster/apps/)查看 diagnostics 信息,根據關鍵字信息明確問題緣由與解決方案:
- Queue's AM resource limit exceeded. 緣由是達到了隊列 AM 可用資源上限,即隊列的 AM 已使用資源和 AM 新申請資源之和超出了隊列的 AM 資源上限,能夠適當調整隊列 AM 可用資源百分比的配置項:yarn.scheduler.capacity..maximum-am-resource-percent。
- User's AM resource limit exceeded. 緣由是達到了應用所屬用戶在該隊列的 AM 可用資源上限,即應用所屬用戶在該隊列的 AM 已使用資源和 AM 新申請資源之和超出了應用所屬用戶在該隊列的 AM 資源上限,能夠適當提升用戶可用 AM 資源比例來解決該問題,相關配置項:yarn.scheduler.capacity..user-limit-factor 與 yarn.scheduler.capacity..minimum-user-limit-percent。
- AM container is launched, waiting for AM container to Register with RM. 大體緣由是 AM 已啓動,但內部初始化未完成,可能有 ZK 鏈接超時等問題,具體緣由需排查 AM 日誌,根據具體問題來解決。
- Application is Activated, waiting for resources to be assigned for AM. 該信息表示應用 AM 檢查已經經過,正在等待調度器分配,此時須要進行調度器層面的資源檢查,跳轉到步驟 4。
3.確認應用確實有 YARN 未能知足的資源請求:從應用列表頁點擊問題應用 ID 進入應用頁面,再點擊下方列表的應用實例 ID 進入應用實例頁面,看 Total Outstanding Resource Requests 列表中是否有 Pending 資源,若是沒有,說明 YARN 已分配完畢,退出該檢查流程,轉去檢查 AM;若是有,說明調度器未能完成分配,跳轉到步驟4;
4.調度器分配問題排查,YARN-9050 支持在 WebUI 上或經過 REST API 自動診斷應用問題,將在 Hadoop3.3.0 發佈,以前的版本仍需進行人工排查:
-
檢查集羣或 queue 資源,scheduler 頁面樹狀圖葉子隊列展開查看資源信息:Effective Max Resource、Used Resources:(1)檢查集羣資源或所在隊列資源或其父隊列資源是否已用完;(2)檢查葉子隊列某維度資源是否接近或達到上限;
-
檢查是否存在資源碎片:(1)檢查集羣 Used 資源和 Reserved 資源之和佔總資源的比例,當集羣資源接近用滿時(例如 90% 以上),可能存在資源碎片的狀況,應用的分配速度就會受影響變慢,由於大部分機器都沒有資源了,機器可用資源不足會被 reserve,reserved 資源達到必定規模後可能致使大部分機器資源被鎖定,後續分配可能就會變慢;(2)檢查 NM 可用資源分佈狀況,即便集羣資源使用率不高,也有多是由於各維度資源分佈不一樣形成,例如 1/2 節點上的內存資源接近用滿 CPU 資源剩餘較多,1/2 節點上的 CPU 資源接近用滿內存資源剩餘較多,申請資源中某一維度資源值配置過大也可能形成沒法申請到資源;
-
檢查是否有高優先級的問題應用頻繁申請並當即釋放資源的問題,這種狀況會形成調度器忙於知足這一個應用的資源請求而無暇顧及其餘應用;
-
檢查是否存在 Container 啓動失敗或剛啓動就自動退出的狀況,能夠查看 Container 日誌(包括 localize 日誌、launch 日誌等)、YARN NM 日誌或 YARN RM 日誌進行排查。
▼ TaskManager 啓動異常: org.apache.hadoop.yarn.exceptions.YarnException: Unauthorized request to start container. This token is expired. current time is ... found ...
該異常在 Flink AM 向 YARN NM 申請啓動 token 已超時的 Container 時拋出,一般緣由是 Flink AM 從 YARN RM 收到這個 Container 好久以後(超過了 Container有效時間,默認 10 分鐘,該 Container 已經被釋放)纔去啓動它,進一步緣由是 Flink 內部在收到 YARN RM 返回的 Container 資源後串行啓動。
當待啓動的 Container 數量較多且分佈式文件存儲如 HDFS 性能較慢(啓動前需上傳 TaskManager 配置)時 Container 啓動請求容易堆積在內部,FLINK-13184 對這個問題進行了優化,一是在啓動前增長了有效性檢查,避免了無心義的配置上傳流程,二是進行了異步多線程優化,加快啓動速度。
▼ Failover 異常 1: java.util.concurrent.TimeoutException: Slot allocation request timed out for ...
異常緣由是申請的 TaskManager 資源沒法正常分配,能夠按 Flink 應用資源分配問題排查思路的步驟4排查問題。
▼ Failover 異常 2: java.util.concurrent.TimeoutException: Heartbeat of TaskManager with id timed out.
異常直接緣由是 TaskManager 心跳超時,進一步緣由可能有:
-
進程已退出,可能自身發生錯誤,或者受到 YARN RM 或 NM 上搶佔機制影響,須要進一步追查 TaskManager 日誌或 YARN RM/NM 日誌;
-
進程仍在運行,集羣網絡問題形成失聯,鏈接超時會自行退出,JobManager 在該異常後會 Failover 自行恢復(從新申請資源並啓動新的 TaskManager);
-
進程 GC 時間過長,多是內存泄露或內存資源配置不合理形成,需根據日誌或分析內存進一步定位具體緣由。
▼ Failover 異常 3: java.lang.Exception: Container released on a lost node
異常緣由是 Container 運行所在節點在 YARN 集羣中被標記爲 LOST,該節點上的全部 Container 都將被 YARN RM 主動釋放並通知 AM,JobManager 收到此異常後會 Failover 自行恢復(從新申請資源並啓動新的 TaskManager),遺留的 TaskManager 進程可在超時後自行退出。
▼ Flink Cluster 疑難問題排查思路
首先根據 JobManager/TaskManager 日誌分析定位問題,完整日誌請參考「Flink 應用的完整日誌如何查看」,若是想獲取 DEBUG 信息,需修改 JobManager/TaskManager 的 log4j 配置(${FLINK_HOME}/conf/log4j.properties)後從新提交運行,對於仍在運行的進程,推薦使用 Java 字節碼注入工具 Byteman 來一窺進程內部的相關狀態,詳細說明請參考:How Do I Install The Agent Into A Running Program?
參考資料
文中綠色字體部分均有跳轉,詳細參考資料請見下方連接:
How Do I Install The Agent Into A Running Program?
Flink on YARN 上、下兩篇文章對 Flink on YARN 應用啓動全流程進行梳理,並對客戶端和 Flink Cluster 的常見問題提供了排查思路,供你們參考,但願在應用實踐中可以對你們有所幫助。
本文做者:楊弢(搏遠)
本文爲雲棲社區原創內容,未經容許不得轉載。