Spark的性能優化案例分析(下)

上一期,我講了軟件性能優化必須經過進行性能測試,並在瞭解軟件架構和技術的基礎上進行。今天,我們通過幾個Spark性能優化的案例,看一看所講的性能優化原則如何落地。如果你忘記了性能優化的原則,可以返回上一期複習一下。

基於軟件性能優化原則和Spark的特點,Spark性能優化可以分解爲下面幾步。

1.性能測試,觀察Spark性能特性和資源(CPU、Memory、Disk、Net)利用情況。

2.分析、尋找資源瓶頸。

3.分析系統架構、代碼,發現資源利用關鍵所在,思考優化策略。

4.代碼、架構、基礎設施調優,優化、平衡資源利用。

5.性能測試,觀察系統性能特性,是否達到優化目的,以及尋找下一個瓶頸點。

下面我們一起進入詳細的案例分析,希望通過這幾個案例,可以幫助你更好地理解Spark的原理,以及性能優化如何實踐落地,希望能對你有所啓發。

案例1:Spark任務文件初始化調優

首先進行性能測試,發現這個視頻圖譜N度級聯關係應用分爲5個job,最後一個job爲保存結果到HDFS,其餘job爲同樣計算過程的反覆迭代。但是發現第一個job比其他job又多了個計算階段stage,如圖中紅圈所示。

通過閱讀程序代碼,發現第一個job需要初始化一個空數組,從而產生了一個stage,但是這個stage在性能測試結果上顯示,花費了14秒的時間,遠遠超出合理的預期範圍。同時,發現這段時間網絡通信也有一定開銷,事實上只是內存數據初始化,代碼上看不出需要進行網絡通信的地方。下圖是其中一臺計算節點的通信開銷,發現在第一個stage,寫通信操作幾乎沒有,讀通信操作大約每秒幾十MB的傳輸速率。

分析Spark運行日誌,發現這個stage主要花費時間並不是處理應用的計算邏輯,而是在從Driver進程下載應用執行代碼。前面說過,Spark和MapReduce都是通過移動計算程序到數據所在的服務器節點,從而節省數據傳輸的網絡通信開銷,並進行分佈式計算,即移動計算比移動數據更划算,而移動計算程序就是在這個階段進行。

這個視頻關係圖譜計算程序因爲依賴一個第三方的程序包,整個計算程序打包後大小超過17MB,這個17MB的JAR包需要部署到所有計算服務器上,即Worker節點上。但是隻傳輸17MB的數據不可能花費這麼多時間啊?

進一步分析Spark日誌和代碼後發現,每個計算節點上會啓動多個Executor進程進行計算,而Spark的策略是每個Executor進程自己去下載應用程序JAR包,當時每臺機器啓動了30個Executor進程,這樣就是4×30=120個進程下載,而Driver進程所在機器是一塊千兆網卡,導致將這些數據傳輸完成花費了14秒的時間。

發現問題以後,解決辦法就顯而易見了。同一臺服務器上的多個Executor進程不必每個都通過網絡下載應用程序,只需要一個進程下載到本地後,其他進程將這個文件copy到自己的工作路徑就可以了。

這段代碼有個技術實現細節需要關注,就是多個進程同時去下載程序包的時候,如何保證只有一個進程去下載,而其他進程阻塞等待,也就是進程間的同步問題。

解決辦法是使用了一個本地文件作爲進程間同步的鎖,只有獲得文件鎖的進程纔去下載,其他進程得不到文件鎖,就阻塞等待,阻塞結束後,檢查本地程序文件是否已經生成。

這個優化實測效果良好,第一個stage從14秒下降到不足1秒,效果顯著。

這個案例的具體代碼你可以參考:
https://github.com/apache/spark/pull/1616

案例2:Spark任務調度優化

繼續前面的性能測試,看看有沒有新的性能瓶頸以及性能指標不合理的地方。我們將4臺Worker機器的CPU使用率進行對比分析,發現CPU使用率有些蹊蹺的地方。




從圖中看到,在第一個job的第二個階段,第三臺機器的CPU使用率和其他機器明顯不同,也就是說計算資源利用不均衡,這種有忙有閒的資源分配方式通常會引起性能問題

分析Spark運行日誌和Spark源代碼,發現當有空閒計算資源的Worker節點向Driver註冊的時候,就會觸發Spark的任務分配,分配的時候使用輪詢方式,每個Worker都會輪流分配任務,保證任務分配均衡,每個服務器都能領到一部分任務。但是爲什麼實測的結果卻是在第二個stage,只有一個Worker服務器領了任務,而其他服務器沒有任何任務可以執行?

進一步分析日誌,發現Worker節點向Driver註冊有先有後,先註冊的Worker開始領取任務,如果需要執行的任務數小於Worker提供的計算單元數,就會出現一個Worker領走所有任務的情況。

而第一個job的第二個stage剛好是這樣的情況,demo數據量不大,按照HDFS默認的Block大小,只有17個Block,第二個stage就是加載這17個Block進行初始迭代計算,只需要17個計算任務就能完成,所以當第三臺服務器先於其他三臺服務器向Driver註冊的時候,觸發Driver的任務分配,領走了所有17個任務。

同時,爲了避免這種一個Worker先註冊先領走全部任務的情況,我們考慮的一個優化策略是增加一個配置項,只有註冊的計算資源數達到一定比例纔開始分配任務,默認值是0.8。

spark.scheduler.minRegisteredResourcesRatio = 0.8

爲了避免註冊計算資源達不到期望資源比例而無法開始分配任務,在啓動任務執行時,又增加了一個配置項,也就是最小等待時間,超過最小等待時間(秒),不管是否達到註冊比例,都開始分配任務。

spark.scheduler.maxRegisteredResourcesWaitingTime = 3

啓用這兩個配置項後,第二個stage的任務被均勻分配到4個Worker服務器上,執行時間縮短了1.32倍。而4臺Worker服務器的CPU利用率也變得很均衡了。




這個案例的具體代碼你可以參考:https://github.com/apache/spark/pull/900
https://github.com/apache/spark/pull/1525

案例3:Spark應用配置優化

看案例2的幾張CPU利用率的圖,我們還發現所有4個Worker服務器的CPU利用率最大隻能達到60%多一點。例如下圖,綠色部分就是CPU空閒。

這種資源利用瓶頸的分析無需分析Spark日誌和源代碼,根據Spark的工作原理,稍加思考就可以發現,當時使用的這些服務器的CPU的核心數是48核,而應用配置的最大Executor數目是120,每臺服務器30個任務,雖然30個任務在每個CPU核上都100%運行,但是總的CPU使用率仍只有60%多。

具體優化也很簡單,設置應用啓動參數的Executor數爲48×4=192即可。

案例4:操作系統配置優化

在性能測試過程中發現,當使用不同服務器的時候,CPU資源利用情況也不同,某些服務器的CPU處於sys態,即系統態運行的佔比非常高,如下圖所示。

圖中紫色爲CPU處於sys態,某些時候sys態佔了CPU總使用率的近80%,這個比例顯然是不合理的,表示雖然CPU很忙,但是沒有執行用戶計算,而是在執行操作系統的計算。

那麼,操作系統究竟在忙什麼,佔用了這麼多CPU時間?通過跟蹤Linux內核執行指令,發現這些sys態的執行指令和Linux的配置參數transparent huge pages有關。

當transparent huge pages打開的時候,sys態CPU消耗就會增加,而不同Linux版本的transparent huge pages默認是否打開是不同的,對於默認打開transparent huge pages的Linux執行下面的指令,關閉transparent huge pages。

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/ transparent_hugepage/defrag

關閉以後,對比前面的CPU消耗,sys佔比明顯下降,總的應用耗時也有明顯下降。

案例5:硬件優化

分析網卡的資源消耗,發現網絡通信是性能的瓶頸,對整個應用的影響非常明顯。比如在第二個、第三個job,網絡通信消耗長達50秒的時間,網絡讀寫通信都達到了網卡的最大吞吐能力,整個集羣都在等待網絡傳輸。

我們知道千兆網卡的最大傳輸速率是每秒125MB,這樣的速率和CPU內存固然沒法比,而雖然比單個磁盤快一些,但是服務器磁盤是8塊磁盤組成的陣列,總的磁盤吞吐量依然碾壓千兆網卡,因此網卡傳輸速率的瓶頸就成爲整個系統的性能瓶頸。

而優化手段其實很簡單粗暴,就是是升級網卡使用萬兆網卡。

硬件優化的效果非常明顯,以前需要50多秒的網絡通信時間,縮短爲10秒左右。從性能曲線上看,網絡通信在剛剛觸及網卡最大傳輸速率的時候,就完成了傳輸,總的計算時間縮短了近100秒。

小結

一般說來,大數據軟件性能優化會涉及硬件、操作系統、大數據產品及其配置、應用程序開發和部署幾個方面。當性能不能滿足需求的時候,先看看各項性能指標是否合理,如果資源沒有全面利用,那麼可能是配置不合理或者大數據應用程序(包括SQL語句)需要優化;如果某項資源利用已經達到極限,那麼就要具體來分析,是集羣資源不足,需要增加新的硬件服務器,還是需要對某項硬件、操作系統或是JVM,甚至是對大數據產品源代碼進行調優。

思考題

關於目前的主要大數據產品,你在學習、使用過程中,從SQL寫法、應用編程、參數配置,到大數據產品自身的架構原理與源碼實現,你有沒有發現有哪些可以進行性能優化的地方?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章