許鵬:Standalone部署模式下臨時文件的生成和清除

jopen 9年前發布 | 11K 次閱讀 分布式/云計算/大數據 Standalone

概要

Spark運行過程中資源的申請和釋放一直是源碼分析時需要關注的重點,從資源種類上來說,有CPU、內存、網絡、磁盤,其中前三者會在進程退出時由OS來負責釋放。而占用的磁盤資源,如果Spark自身不及時的清理,就勢必會造成文件的堆積,直至磁盤被占滿不可用。

因此有必要弄清楚Spark運行過程中產生的臨時文件及其釋放的時機,這樣有助于部署和運維過程中采取相應的文件清理策略。

許鵬:Standalone部署模式下臨時文件的生成和清除

部署時的第三方包依賴

再提出具體的疑問之前,先回顧一下standalone的部署模式。

在standalone下又分為client模式和cluster模式,其中client模式下,driver和client運行于同一JVM中,不由worker啟動,該JVM進程直到spark application計算完成返回結果后才退出。如下圖所示。

而在cluster模式下,driver由worker啟動,client在確認spark application成功提交給cluster后直接退出,并不等待spark application運行結果返回。如下圖所示

許鵬:Standalone部署模式下臨時文件的生成和清除

從部署圖來進行分析,每個JVM進程在啟動時的文件依賴如何得到滿足。

1. Master進程最為簡單,除了spark jar包之外,不存在第三方庫依賴

2. Driver和Executor在運行的時候都有可能存在第三方包依賴,分開來講

  1. Driver比較簡單,spark-submit在提交的時候會指定所要依賴的jar文件從哪里讀取
  2. 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運行時生成的日志信息。

許鵬:Standalone部署模式下臨時文件的生成和清除

實驗1

運行spark-shell,查看在/tmp目錄下會新產生哪些目錄。

#$SPARK_HOME/bin/spark-shell

在/tmp目錄下會新增四個與spark-shell相關的文件夾,

spark+隨機數目錄

分別用于driver本身,driver創建的tmp目錄,httpfileserver創建的目錄

spark-local目錄

用以存放executor執行過程中生成的shuffle output和cache的目錄

許鵬:Standalone部署模式下臨時文件的生成和清除

運行中的臨時文件Executor在運行的時候,會生成Shuffle Output,如果對RDD進行Cache的話,還有可能會將RDD的內容吐到磁盤中。這些都意味著需要有一個文件夾來容納這些東西。

在上文中提到的形如spark-local-*的目錄就是用以存儲executor運行時生成的臨時文件。

可以通過兩個簡單的實驗來看spark-local-*目錄下內容的變化。

實驗2 不進行RDD Cache

許鵬:Standalone部署模式下臨時文件的生成和清除

進入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)


上述指令會生成兩個不同的Stage, 所以會有Shuffle Output,具體劃分原因就不再細述了。

如果使用的是spark 1.2.x,可以看到有在spark-local-*目錄下有index文件生成。

實驗3 進行RDD Cache

許鵬:Standalone部署模式下臨時文件的生成和清除

進行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

$SPARK_LOCAL_DIRS下的*_cache文件是為了避免同一臺機器中多個executor執行同一application時多次下載第三方依賴的問題而引進的patch,詳見JIRA case spark-2713. 對就的代碼見spark/util/Utils.java中的fetchFile函數

如果已經在使用了,有什么辦法來清除呢?暴力刪除,不管三七二十一,過一段時間將已經存在的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.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相關。

參考

  1. https://spark.apache.org/docs/1.2.0/submitting-applications.html
  2. https://spark.apache.org/docs/1.2.0/spark-standalone.html
  3. http://mail-archives.apache.org/mod_mbox/spark-commits/201410.mbox/%3C2c2ce06abc7d48d48f17f8e458a53219@git.apache.org%3E
  4. https://issues.apache.org/jira/browse/SPARK-4323
  5. https://issues.apache.org/jira/browse/SPARK-2713

文章出處:http://www.csdn.net/article/2015-03-03/2824095

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!