Spark Submit --files 添加文件

一.引言

當一個分佈式任務中一個文件需要在全局使用時,最常見的方法就是使用廣播的形式,在dirver端讀取隨後分發到excutor,這裏需要的時間是

1) dirver端讀取文件時間

2) 廣播分發到各excutor的時間

當文件大小逐漸增加到一個閾值,或者內存資源有瓶頸時,廣播的時間就會變長,這時候就需要和下面這種方式進行比較,看哪種方式時間最快

1) --files 添加文件

2) 直接在excutor讀取文件,各個task使用

 

二.Spark Submit 腳本 --files 添加

Tips:這裏適用於yarn-cluster模式,如果是本地模式的話直接 scala.io.Source.fromFile(fileName) 即可。

1.提交日誌信息查看

這裏先鋪墊一下,--files 傳輸的文件:

如果與當前提交集羣處於同一集羣,會提示當前數據源與目標文件存儲系統相同,此時不會觸發拷貝

INFO Client: Source and destination file systems are the same. Not copying

如果與當前提交集羣處於不同集羣,則會將源文件從源路徑更新至當前文件存儲系統

INFO Client: Uploading resource

2.腳本傳入 --files

#!/bin/bash

spark-submit \
--class your.class \
--master yarn \
--executor-cores 2 \
--driver-memory 2g \
--deploy-mode cluster \
--executor-memory 2G \
--files "viewfs://c9/ ... /localMaterial" \
--num-executors 2 \
./your.jar --local false

資源配置這些根據自己需求配置,唯一需要注意的就是這裏 --files 傳入的路徑地址的 HDFS 前綴要和上面日誌提交時目標路徑的 HDFS 路徑保持一致,否則會報 FileNotExist 的錯。

 

三. Excutor 端讀取 --files 傳入文件

通過 SparkFiles.get(fileName)獲取 --filse 傳入的文件,這裏只需要文件名即可,不需要完整的文件路徑,然後通過Scala.io.Source讀即可,接下來partition內的邏輯就都可以使用該文件了。

    val sc = new SparkContext(conf)
    val inputRdd = sc.textFile(input)

    val fileName = "localMaterial"
    println("Driver端: " + SparkFiles.get(fileName))

    inputRdd.foreachPartition(partition => {
      val path = SparkFiles.get(fileName)
      println("Excutor端: " + path)
      val info = scala.io.Source.fromFile(path).getLines().toArray

      partition.foreach(line => {
        ...
      })

    })

 

有一點需要注意的就是該文件在 Dirver 端get得到的路徑與 Excutor 端get到的路徑時不一致的,所以要區分是要在dirver初始化該文件還是在excutor端初始化:

Dirver端:

/data10/hadoop/local/.../application_1594195336447_37512905/spark-b06afbf7-8618-49f3-ab64-cd40ba3b3ee9/userFiles-d14c7c91-44ac-4f09-b27e-a5467445f080/localMaterial

Excutor端:

/data9/hadoop/local/.../application_1594195336447_37509831/container_e29_1594195336447_37509831_01_000007/./localMaterial

這是因爲 --files 會先經過 dirver 端處理,dirver會調用 SparkFiles.addFile() 獲取文件到dirver的臨時目錄,隨後 excutor 讀取的文件是從 dirver 這裏 fetch 到 container 的工作目錄,所有造成了兩端的目錄位置不一致,如果將 dirver 端的路徑直接傳給 excutor 端,同樣會報 FileNotFound 的錯誤。

 

四. --files 傳入多個文件

傳入多個文件需要修改submit腳本和程序內部:

1.submit腳本

—files 內文件按 ’,’ 號隔開,例如:

--files "viewfs://c9/.../localMaterial,viewfs://c9/...localMaterial1" \

2.spark 內部讀取

    inputRdd.foreachPartition(partition => {
      val path1 = SparkFiles.get("localMateria")
      val path2 = SparkFiles.get("localMaterial")
      ...

      partition.foreach(line => {
        ...
      })

    })

 dirver端,excutor端都支持讀取 --files 傳入的多個路徑的文件:

 

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