本文作者胡夢宇,知乎大資料架構開發工程師,主要負責知乎內部大資料元件的二次開發和資料平臺建設。
背景
Flink 因為其可靠性和易用性,已經成為當前最流行的流處理框架之一,在流計算領域佔據了主導地位。早在 18 年知乎就引入了 Flink,發展到現在,Flink 已經成為知乎內部最重要的元件之一,積累了 4000 多個 Flink 實時任務,每天處理 PB 級的資料。
Flink 的部署方式有多種,根據資源排程器來分類,大致可分為 standalone、Flink on YARN、Flink on Kubernetes 等。目前知乎內部使用的部署方式是 Flink 官方提供的 native Kubernetes。談到 Kubernetes,就不得不說容器映象的問題,因為 Flink 任務的依賴多種多樣,如何給 Flink 打映象也是一個比較頭疼的問題。
Flink 映象及依賴處理
Flink 的任務大致可分為兩類,第一類是 Flink SQL 任務,Flink SQL 任務的依賴大致有以下幾種:
- 官方的 connector JAR 包,如 flink-hive-connector、flink-jdbc-connector、flink-kafka-connector 等;
- 非官方或者是內部實現的 connector JAR 包;
- 使用者的 UDF JAR 包,一些複雜的計算邏輯,使用者可能會自己實現 UDF。
第二類 Flink 任務是 Flink 的 jar 包任務,除了以上三種依賴,還需要依賴使用者自己寫的 Flink jar 程式包。
顯然,對於每一個 Flink 任務,它的依賴不盡相同,我們也不可能為每一個 Flink 任務單獨打一個映象,我們目前的處理如下:
- 將依賴進行分類,分為穩定依賴和非穩定依賴;
- 穩定依賴包括元件(如 Flink、JDK 等)以及官方的 connector 包,這類依賴十分穩定,只會在 Flink 版本升級和 bug 修復這兩種情況下進行改動,因此我們會在構建映象時,將這類依賴打入映象;
- 非穩定依賴包括第三方的 connector 和使用者自己的 JAR 包。第三方的 connector 因為不是 Flink 官方維護,所以出問題需要修復的概率相對更大;使用者自己的 JAR 包對於每個任務來說都不相同,而且使用者會經常改動重新提交。對於這類不穩定的依賴,我們會動態注入,注入的方式是將依賴存入分散式檔案系統,在容器啟動的時候,利用 pre command 下載進容器裡。
經過以上處理,Flink 映象具備了一定的動態載入依賴的能力,Flink Job 的啟動流程大致如下:
檔案系統選取
HDFS 存放依賴的痛點
存放 Flink 依賴的檔案系統在之前我們一直都是選用的 HDFS, 但是在使用過程中我們遇到了以下痛點:
- NameNode 在任務高峰期壓力過大,容器在下載依賴時向 NameNode 請求檔案後設資料會存在卡頓的情況,有些小的批任務,任務本身可能只需要執行十幾秒,但是因為 NameNode 壓力過大,導致下載依賴可能需要幾分鐘;
- 目前 Flink 叢集我們是多資料中心部署,但是 HDFS 只有一個離線機房大叢集,這樣會存在跨資料中心拉檔案的情況,消耗專線頻寬;
- 有一些特殊的 Flink 任務完全不依賴 HDFS,換句話說它既不使用 checkpoint 也不讀寫 HDFS,但是因為 Flink 容器的依賴存放在 HDFS 上,導致這類任務依然離不開 HDFS。
使用物件儲存的痛點
後面我們將 HDFS 換成了物件儲存,解決了 HDFS 的一些痛點,但是很快我們發現了新的問題 — 物件儲存單執行緒下載的速度慢。物件儲存下載加速可選的方案一般有以下幾種:
- 使用多執行緒下載進行分段下載,但是容器的 pre command 其實只適合執行一些比較簡單的 shell 命令,如果採用分段下載,就必須對這一塊進行比較大的改造,這是一個比較大的痛點;
- 給物件儲存加代理層做快取,加速的事情由代理來做,客戶端依然可以單執行緒讀取。這種辦法的缺點是需要額外維護一個物件儲存的代理元件,元件的穩定性也需要有保障。
嘗試 JuiceFS
比較湊巧的是公司內部正在做 JuiceFS 的 POC, 有現成的物件儲存代理層可用,我們對其進行了一系列測試,發現 JuiceFS 完全滿足我們這個場景的需求,讓我們比較驚喜的地方有以下幾點:
- JuiceFS 自帶 S3 gateway 完美相容 S3 物件儲存協議,能夠讓我們很快上線,無需任何改動,並且 S3 gateway 本身無狀態,擴縮容非常方便;
- JuiceFS 自帶快取加速功能,經過測試,用 JuiceFS 代理物件儲存後,單執行緒讀取檔案的速度是原來的 4 倍;
- JuiceFS 提供本地檔案系統掛載的方式,後面可以嘗試依賴直接掛載進容器目錄;
- JuiceFS 可選用後設資料與儲存分離部署的方式,儲存我們選用原來的物件儲存,雲廠商保證 11 個 9 的可用性;後設資料我們選用分散式 KV 系統—TiKV,選用 TiKV 的原因是我們線上架構組的同事對 TiKV 有著豐富的開發和運維經驗,SLA 能夠得到極大的保障。這樣 JuiceFS 的可用性和擴充套件性是非常強的。
JuiceFS 上線
JuiceFS 的上線過程分為以下階段:
- 資料遷移,我們需要將原先儲存在 HDFS 和物件儲存上的資料同步到 JuiceFS 上,因為 JuiceFS 提供了資料同步的工具,並且 Flink 的依賴也不是特別大,所以這部分工作我們很快就完成了;
- 修改 Flink 映象拉取依賴的地址,因為 JuiceFS 相容物件儲存協議,我們只需要在平臺側修改原來的物件儲存的 endpoint 為 JuiceFS S3 gateway 的地址即可。
JuiceFS 上線後,我們 Flink 任務啟動的流程圖大致如下:
相比於使用 HDFS 的方式,我們能得到一個可預期的容器啟動時間,容器下載依賴的速度不會受業務高峰期的影響;相比於原生的物件儲存,容器下載依賴的速度提高約 4 倍。
展望
從開始調研 JuiceFS 到 JuiceFS 上線花費時間不到半個月,主要是因為 JuiceFS 的文件十分完備,讓我們少走了很多彎路,其次是 JuiceFS 社群的夥伴也有問必答,因此我們的上線過程十分順利。
初步嘗試 JuiceFS 給我們帶來的收益還是比較明顯的,後續我們會考慮將 JuiceFS 應用在資料湖場景和演算法模型載入的場景,讓我們資料的使用更加靈活和高效。
專案地址: Github (https://github.com/juicedata/juicefs)如有幫助的話歡迎關注我們喲! (0ᴗ0✿)