標籤:
未經本人同意嚴禁轉載,徽滬一郎。
概要
在Standalone部署模式下,Spark運行過程中會建立哪些臨時性目錄及檔案,這些臨時目錄和檔案又是在什麼時候被清理,本文將就這些問題做深入細緻的解答。
從資源使用的方面來看,一個進程運行期間會利用到這四個方面的資源,分別是CPU,記憶體,磁碟和網路。進程退出之後,CPU,記憶體和網路都會由作業系統負責釋放掉,但是運行過程中產生臨時檔案如果進程自己不在退出之前有效清除,就會留下一地雞毛,浪費有效儲存空間。
部署時的第三方依賴
再提出具體的疑問之前,先回顧一下standalone的部署模式
在standalone下又分為client模式和cluster模式,其中client模式下,driver和client運行於同一JVM中,不由worker啟動,該JVM進程直到spark application計算完成返回結果後才退出。如所示。
而在cluster模式下,driver由worker啟動,client在確認spark application成功提交給cluster後直接退出,並不等待spark application運行結果返回。如所示
從部署圖來進行分析,每個JVM進程在啟動時的檔案依賴如何得到滿足。
- Master進程最為簡單,除了spark jar包之外,不存在第三方庫依賴
- Driver和Executor在啟動並執行時候都有可能存在第三方包依賴,分開來講
- Driver比較簡單,spark-submit在提交的時候會指定所要依賴的jar檔案從哪裡讀取
- Executor由worker來啟動,worker需要下載Executor啟動時所需要的jar檔案,那麼從哪裡下載呢。
為瞭解決Executor啟動時依賴的Jar問題,Driver在啟動的時候要啟動HttpFileServer儲存第三方jar包,然後由worker從HttpFileServer來擷取。為此HttpFileServer需要建立相應的目錄,而Worker也需要建立相應的目錄。
HttpFileServer建立目錄的過程詳見於SparkEnv.scala中create函數。
spark會為每一個提交的application產生一個檔案夾,預設位於$SPARK_HOME/work目錄下,用以存放從HttpFileServer下載下來的第三方庫依賴及Executor運行時產生的日誌資訊。
實驗1
運行spark-shell,查看在/tmp目錄下會新產生哪些目錄。
#$SPARK_HOME/bin/spark-shell
在/tmp目錄下會新增四個與spark-shell相關的檔案夾
spark+隨機數目錄
分別用於driver本身,driver建立的tmp目錄,httpfileserver建立的目錄
spark-local目錄
用以存放executor執行過程中產生的shuffle output和cache的內容
運行中的臨時檔案
Executor在啟動並執行時候,會產生Shuffle Output,如果對RDD進行Cache的話,還有可能會將RDD的內容吐到磁碟中。這些都意味著需要有一個檔案夾來容納這些東西。
上文中提到的形如spark-local-*的目錄就是用以儲存executor運行時產生的臨時檔案。
可以通過兩個簡單的實驗來看spark-local-*目錄下內容的變化。
實驗2:不進行RDD Cache
進入spark-shell之後運行
spark-shell>sc.textFile(“README.md”).flatMap(l=>l.split(“ “)).map(w=>(w,1)).reduceByKey(_ + _).foreach(println)
上述指令會產生兩個不同的Stage, 所以會有Shuffle Output,具體劃分原因就不再細述了。
如果使用的是spark 1.2.x,可以看到有在spark-local-*目錄下有index檔案產生。
實驗3: 進行RDD Cache
進入spark-shell之後運行
spark-shell>val rdd1 = sc.textFile(“README.md”).flatMap(l=>l.split(“ “)).map(w=>(w,1)).reduceByKey(_ + _)spark-shell> rdd1.persist(MEMORY_AND_DISK_SER)spark-shell>rdd1.foreach(println)
上述指令執行後,不僅會有index檔案還會有形如rdd*的檔案產生,這些rdd打頭的檔案就是cache內容。
配置項
可以通過在$SPARK_HOME/conf/spark-env.sh中指定配置內容來更改預設的儲存位置。
SPARK_WORK_DIR 指定work目錄,預設是$SPARK_HOME/work子目錄
SPARK_LOCAL_DIRS 指定executor運行產生的臨時檔案目錄,預設是/tmp,由於/tmp目錄有可能是採用了tmpfs,建議在實際部署中將其更改到其它目錄
檔案的清理
上述過程中產生的臨時檔案在什麼時候會被刪除掉呢?
也許第一感覺就是spark application結束啟動並執行時候唄,直覺有時不見得就是對的。
SPARK_LOCAL_DIRS下的產生的檔案夾,確實會在應用程式退出的時候自動清理掉,如果觀察仔細的話,還會發現在spark_local_dirs目錄有有諸如*_cache和*_lock的檔案,它們沒有被自動清除。這是一個BUG,可以會在spark 1.3中加以更正。有關該BUG的具體描述,參考spark-4323 https://issues.apache.org/jira/browse/SPARK-4323
$SPARK_LOCAL_DIRS下的*_cache檔案是為了避免同一台機器中多個executor執行同一application時多次下載第三方依賴的問題而引進的patch,詳見JIRA case spark-2713. 對就的代碼見spark/util/Utils.java中的fetchFile函數。https://issues.apache.org/jira/browse/SPARK-2713
如果已經在使用了,有什麼辦法來清除呢?暴力刪除,不管三七二十一,過一段時間將已經存在的cache和lock全部刪除。這不會有什麼副作用,大不了executor再去下載一次罷了
find $SPARK_LOCAL_DIRS -max-depth 1 -type f -mtime 1 -exec rm -- {} \;
而SPARK_WORK_DIR目錄下的形如app-timestamp-seqid的檔案夾預設不會自動清除。
那麼可以設定哪些選項來自動清除已經停止啟動並執行application的檔案夾呢?當然有。
在spark-env.sh中加入如下內容
SPARK_WORKER_OPTS=”-Dspark.worker.cleanup.enabled=true”
注意官方文檔中說不管程式是否已經停止,都會刪除檔案夾,這是不準確的,只有停止掉的程式檔案夾才會被刪除,我已提交相應的PR.
實驗4
寫一個簡單的WordCount,然後以Standalone Cluster模式提交運行,察看$SPARK_LOCAL_DIRS下檔案內容的變化。
import org.apache.spark._import org.apache.spark.{SparkConf, SparkContext}import org.apache.spark.SparkContext._import java.util.Dateobject HelloApp { def main(args: Array[String]): Unit = { val conf = new SparkConf() val sc = new SparkContext() val fileName = "$SPARK_HOME/README.md" val rdd1 = sc.textFile(fileName).flatMap(l => l.split(" ")).map(w => (w, 1)) rdd1.reduceByKey(_ + _).foreach(println) var i: Int = 0 while ( i < 10 ) { Thread.sleep(10000) i = i + 1 } }}
提交運行
spark-submit –class HelloApp –master spark://127.0.0.1:7077 --deploy-mode cluster HelloApp.jar
小結
本文通過幾個簡單易行的實驗來觀測standalone模式下臨時檔案的產生和清除,希望有助於理解spark中磁碟資源的申請和釋放過程。
Spark部署時相關的配置項比較多,如果先進行分類,然後再去配置會容易許多,分類有CPU、Memory、Network、Security、Disk及Akka相關。
參考資料
- https://spark.apache.org/docs/1.2.0/submitting-applications.html
- https://spark.apache.org/docs/1.2.0/spark-standalone.html
- http://mail-archives.apache.org/mod_mbox/spark-commits/201410.mbox/%[email protected]%3E
- https://issues.apache.org/jira/browse/SPARK-4323
- https://issues.apache.org/jira/browse/SPARK-2713
Apache Spark技術實戰之8:Standalone部署模式下的臨時檔案清理