最近接手了一個改造多平臺日誌服務的需求,通過梳理,我認爲以前服務在設計上存在缺陷。通過一段時間的技術方案調研,最終咱們決定選擇使用 Flink 重構該服務。html
目前重構後的服務已成功經受了國慶節流量洪峯的考驗,今日特來總結回顧,和你們分享一下經驗。sql
在瞭解改造服務的需求前,咱們首先要明確,要解決什麼問題以及目前的服務是如何解決的。數據庫
當前的業務邏輯仍是比較清晰的:編程
咱們面臨的痛點和難點:網絡
針對以上業務需求,有同窗提出:「咱們能夠把全部原始數據放到數據庫中,後續的 ETL 能夠經過 SQL 實現。」架構
若是你一聽到"數據庫"想到的就是 Pg、Mysql、Oracle 等,以爲這個方案不具備可行性,那你就錯了。數據庫的類型和維度是很是豐富的,以下圖所示:dom
按業務負載特徵,關係型數據庫可分爲 OLTP 數據庫(交易型)和 OLAP 數據庫(分析型) :編程語言
方案 1 小結函數式編程
OLAP 的使用場景符合咱們的需求,爲此咱們還專門去調研了一下 ClickHouse。可是有一個因素讓咱們最終放棄了使用 OLAP。請注意,數據庫存儲的數據都是二維的,有行和列兩個維度。可是日誌只有行一個維度。若是說爲了把日誌存入數據庫把每行日誌都切分,那統計字段的需求也就順手實現了,又何須存到數據呢?函數
因此,OLAP 使用場景隱含的一個特色是:存入的數據須要被多維度反覆分析的。這樣纔有把數據存入數據庫的動力,像咱們當前的需求對日誌進行簡單的變形後仍舊以文本日誌的形式輸出,使用 OLAP 是不合適的。
看到這,熟悉大數據的同窗可能會以爲咱們水平很 Low,由於業務需求歸根到底就是三個字:批處理。
那咱們爲何第一時間沒有考慮上大數據呢?
大數據確實如雷貫耳,但如今咱們的日誌處理這塊大部分都是用 Golang 實現的,團隊內的其餘業務用了 Python、Lua、C,就是沒有用過到 Java。而目前大數據都是基於 JVM 開發的。Golang 調用這些服務沒有一個好用的客戶端。
因此基於團隊目前的技術儲備,大數據纔沒有成爲咱們的首選。可是從目前的情況來看大數據是最優解了。那麼咱們該選用大數據的什麼組件實現需求呢?
放棄使用數據庫直接使用 HDFS 存儲日誌文件,應該是毋庸置疑的。
咱們需求是離線批處理數據,對時效性沒有要求,MapReduce 和 Hive 都能知足需求。可是 MapReduce 與 Hive 相比,Hive 在 MapReduce 上作了一層封裝而且支持 SQL。看起來 Hive 是很是合適的。
那爲何最終放棄了 Hive 呢?
方案 2 小結
再合適的技術方案不能落地也是空談。可是技術方案想要落地時,已經不是一個單純的技術問題了,資源限制,團隊限制等都須要考慮在內。
一個優秀的技術方案立足於解決當下的問題,而且能放眼將來勾畫藍圖,這樣你們以爲 "有利可圖",才願意跟你一塊兒折騰。
通用的計算引擎
雖然使用 HDFS 的團隊不同意在他們的機器上跑 Hive,可是咱們把日誌數據存到他們的 HDFS 上仍是沒問題的。在已知 "存儲和分離是趨勢" 是前提的基礎下,"咱們到底須要什麼" 這個問題已經有答案了。
咱們須要的是一個通用的計算引擎。存儲已經剝離給 HDFS 了,因此咱們只須要找一個工具,幫咱們處理 ETL 就能夠了。Spark 和 Flink 正是這樣的場景。
Spark 與 Flink 初次交鋒
Spark 和 Flink 之間,咱們堅決果斷地選擇了 Spark。緣由很是簡單:
揮淚斬 Spark
前文已經交代過了,咱們否決掉 Hive 的一個重要因素是沒有足夠的機器資源。因此咱們把 Spark 直接部署到雲平臺上。
對於我司的雲平臺要補充一些細節。
咱們的雲平臺是基於 K8S 二次開發的,目前還在迭代當中,所以"Spark on K8S" 的運行模式咱們暫時用不了。在這樣的狀況下,咱們採用了 "Spark Standalone" 的模式。Standalone 模式,也就是Master Slaver 模式,相似於 Nginx 那樣的架構,Master 節點負責接收分發任務,Slaver 節點負責"幹活"。
等到咱們在雲平臺上以 "Spark Standalone" 模式部署好了,跑了幾個測試 Case 發現了新問題。咱們的雲平臺與辦公網絡是隔離的,若是辦公網絡想訪問雲平臺的某個 Docker 容器,須要配置域名。而 Spark 的管理頁面上不少 URL 的 domain 是所在機器的 IP,容器的 IP 是虛擬 IP,容器重啓後IP 就會改變。具體如圖:
Spark 的管理平臺很是重要,由於能從這上面看到當前各個節點運行狀況,任務的異常信息等,如今不少連接不能訪問,不利於咱們對 Spark 任務進行問題排查和調優。基於這個緣由,咱們最終放棄了 Spark。
方案 3 小結
Spark 你真的很優秀,擅長批處理,如此成熟,還有函數式的基因 。。。這些優勢早讓我傾心不已。
Spark 你真的是個好人,若是不是雲平臺的限制,我必定選擇你。
Spark,對不起。
給 Spark 發無缺人卡後,咱們看一看新歡 Flink。不客氣的說,Flink 初期時不少實現都是抄的 Spark,因此兩者的不少概念類似。因此 Flink 一樣有 Standalone 模式,咱們在部署階段沒遇到任何問題。
在跑了幾個 Flink 測試 Case 後,咱們由衷的感嘆 Flink 真香。
放棄 Spark 時咱們的痛點在於 "部署在雲平臺上的 Spark 服務的管理界面不少功能沒法使用",而 Flink 的管理平臺徹底沒有這個問題。除此以外,Flink 管理平臺的 "顏值" 和功能都是 Spark 沒法比擬的。
管理平臺顏值對比
對比之下,Spark 的頁面徹底是個"黃臉婆"。
Flink 管理平臺功能
因爲 Spark 的功能不少不能使用,因此就不重點和 Flink 作比較了。這裏只說 Flink 幾個讓人眼前一亮的功能。
部署了 Flink 或 Spark 服務後,該如何下發計算任務呢? 通常是經過 bin 目錄下的一個名稱中包含 submit 的可執行程序。那若是想把 Flink 或 Spark 作成微服務,經過 http 接口去下發任務呢?
Spark1.0 的時候支持 http,2.0時這個功能基本上廢掉了,不少參數不支持了,把 http 這個功能交由 jobService 一個第三方開源組件去實現。這個 jobService 的開源組件對雲平臺的支持也很是不友好。因此在咱們看來,Spark 經過 Http 下發任務的路子基本被堵死了。
反觀 Flink,管理平臺的接口是 Restful 的,不只支持 Http 下發計算任務,還能夠經過相關接口查看任務狀態和獲取異常或返回值。
Flink 的任務分爲幾個不一樣的階段,每一個不一樣的階段有不一樣的顏色。這樣僅從顏色就能夠判斷出當前 Flink 任務執行的大體狀況。以下圖:
在任務詳情頁面,會有任務分解圖和任務執行耗時表格,這兩個結合起來可以知道固然 Flink 任務是如何分解的,是否出現數據傾斜的狀況,哪一個步驟耗時最多,是否有優化的空間。
這就是作批處理技術選型時候的心路歷程,隨筆記了下來,但願對你們有所幫助。