接觸Flink一段時間了,遇到了一些問題,其中有一個checkpoint失敗導致作業重啟的問題,遇到了很多次,重啟之后一般也能恢復正常,沒有太在意,最近2天有同事又頻繁遇到,這里記錄一下解決方案和分析程序,
我們的flink測驗環境有3個節點,部署架構是每個flink節點上部署一個HDFS的DataNode節點,hdfs用于flink的checkpoint和savepoint
現象
看日志是說有個3個datanode活著,檔案副本是1,但是寫檔案失敗
There are 3 datanode(s) running and no node(s) are excluded
網上搜了一下這種報錯,沒有直接的答案,我看了下namenode的日志,沒有更多直接的資訊
50070 web ui上看一切正常,datanode的剩余空間都還有很多,使用率不到10%
我試了一下往hdfs上put一個檔案再get下來,都ok,說明hdfs服務沒有問題,datanode也是通的
日志現象1
繼續前后翻了一下namenode的日志,注意到有一些warning資訊,
這時候懷疑塊放置策略有問題
按照日志提示打開相應的的debug開關
修改
etc/hadoop/log4j.properties
找到
log4j.logger.org.apache.hadoop.fs.s3a.S3AFileSystem=WARN
照抄這個格式,在下面添加
log4j.logger.org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicy=DEBUG
log4j.logger.org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor=DEBUG
log4j.logger.org.apache.hadoop.net.NetworkTopology=DEBUG
重啟namenode,然后重跑flink作業
日志現象2
這時候看到的問題是機架感知策略無法滿足,因為我們沒有提供機架映射腳本,默認同一個機架,但是仔細想想跟這個應該也沒有關系
因為很多生產環境的hdfs其實都不配置機架映射腳本,并且導致checkpoint失敗的問題并不是一直存在,最起碼put/get檔案都是正常的,
這時候開始考慮看一下hdfs的原始碼了,根據上面的日志呼叫堆疊,先看到BlockPlacementPolicyDefault以及相關的DatanodeDescriptor
這些原始碼大致的意思是當給一個塊選擇一個datanode的時候,要對這個datanode進行一些檢查,比如看下剩余空間,看下繁忙程度
當我們的問題復現的時候,觀察日志會發現一些與此相關的關鍵資訊
這個日志的意思是,存盤空間有43G,分配塊實際需要100多M,但是scheduled大小就超過43G,因此我們認為正常的datanode,namenode認為它空間不足了
原因
scheduled大小含義是什么呢? 根據代碼可以看到scheduled大小是塊大小跟一個計數器做乘法,計數器代表的其實是新建檔案塊數量計數器,hdfs根據這兩個引數評估可能需要的存盤空間,相當于給每個datanode預定了一定的空間,預定的空間在檔案寫入后,計算完真實的占用空間后,還會調整回來,
了解這個原理之后,可以判斷的是datanode在一段時間內被預定了太多的空間,
flink的checkpoint機制可以參考這一篇https://www.jianshu.com/p/9c587bd491fc
大致的意思是taskmanager上的很多任務執行緒都會寫hdfs
看了下hdfs的目錄結構,有大量的類似uuid命名checkpoint檔案,同時每個檔案都很小
當我們的作業并發較大時,相應的在hdfs上就會創建更多的checkpoint檔案,盡管我們的檔案大小只有幾K,但是在每一個datanode預定的空間都是128M乘以分配到的檔案數量(檔案很小,不超過128M),那么43G的空間,最多預定多少檔案呢?除一下也就是300多個,三個節點也就是最多900個,我們有多個作業,總并發較大,在預留空間完全釋放前,是很容易出現這個問題的,
之前知道hdfs不適合存盤小檔案,原因是大量小檔案會導致inode消耗以及block location這些元資料增長,讓namenode記憶體吃緊,這個例子還表明
當blocksize設定較大,檔案大小卻遠小于blocksize時,大量這種小檔案會導致datanode直接"不可用",
解決辦法
塊大小不是集群屬性,是檔案屬性,客戶端可以設定的,flink這時候每個taskmanager和jobmanager都是hdfs的"客戶端",根據flink檔案,我們可以做如下配置
1、在conf/flink-conf.yaml中指定一個hdfs的組態檔路徑
fs.hdfs.hadoopconf: /home/xxxx/flink/conf
這里跟flink的組態檔路徑選擇同一個目錄
2、放進去2個組態檔,一個core-site.xml一個是hdfs-site.xml
core-site.xml可以不放,如果checkpoint和savepoint指定了具體的hdfs地址的話,
hdfs-site.xml里加上blockSize配置即可,比如這里我們給它設定為1M
具體塊大小如何設定,需要觀察自己的作業狀態檔案大小自己靈活調整,
重啟flink集群,提交作業即可,運行時可以觀察下hdfs的fsimage大小,注意不要因為塊太小,小檔案太多導致元資料過大,
小結
我們已經將該問題同步到集群自動化部署腳本中,部署時會專門添加blocksize的配置,
flink這套依賴hdfs的checkpoint方案對于輕量級的流計算場景稍顯臃腫,checkpoint的分布式存盤不管是直接filesystem還是rocksDB都需要hdfs,其實從checkpoint原理和資料型別考慮,es應該也是不錯的選擇,遺憾的是社區并沒有提供這種方案,
歡迎關注我的公眾號:【 Java爛豬皮 】,獲得獨家整理的學習資源、日常干貨及福利贈送,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/68302.html
標籤:Java
下一篇:Java基礎 -- 七大基本原則
