未經本人贊成嚴禁轉載,徽滬一郎。html
在Standalone部署模式下,Spark運行過程當中會建立哪些臨時性目錄及文件,這些臨時目錄和文件又是在何時被清理,本文將就這些問題作深刻細緻的解答。java
從資源使用的方面來看,一個進程運行期間會利用到這四個方面的資源,分別是CPU,內存,磁盤和網絡。進程退出以後,CPU,內存和網絡都會由操做系統負責釋放掉,可是運行過程當中產生臨時文件若是進程本身不在退出以前有效清除,就會留下一地雞毛,浪費有效的存儲空間。git
再提出具體的疑問以前,先回顧一下standalone的部署模式shell
在standalone下又分爲client模式和cluster模式,其中client模式下,driver和client運行於同一JVM中,不禁worker啓動,該JVM進程直到spark application計算完成返回結果後才退出。以下圖所示。apache
而在cluster模式下,driver由worker啓動,client在確認spark application成功提交給cluster後直接退出,並不等待spark application運行結果返回。以下圖所示bash
從部署圖來進行分析,每一個JVM進程在啓動時的文件依賴如何獲得知足。網絡
爲了解決Executor啓動時依賴的Jar問題,Driver在啓動的時候要啓動HttpFileServer存儲第三方jar包,而後由worker從HttpFileServer來獲取。爲此HttpFileServer須要建立相應的目錄,而Worker也須要建立相應的目錄。app
HttpFileServer建立目錄的過程詳見於SparkEnv.scala中create函數。函數
spark會爲每個提交的application生成一個文件夾,默認位於$SPARK_HOME/work目錄下,用以存放從HttpFileServer下載下來的第三方庫依賴及Executor運行時生成的日誌信息。fetch
運行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-*目錄下內容的變化。
進入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文件生成。
進入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.
若是Spark應用程序須要長時間運行,生成的許多shuffle output什麼時候再清理呢?能夠經過配置spark.cleaner.ttl來設置清理的時間。
寫一個簡單的WordCount,而後以Standalone Cluster模式提交運行,察看$SPARK_LOCAL_DIRS下文件內容的變化。
import org.apache.spark._ import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.SparkContext._ import java.util.Date object 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相關。