原理簡述
Yarn 模式是把資源統一交給 Yarn 集群來管理,其優點在於實現了 application 的多樣性,如 MapReduce 程序、HBase 集群、Storm 集群、spark 集群等;
Yarn 模式有兩種運行模式:client 和 cluster,區別在於
client 模式的 Driver 運行在 client 端,而 client 端可能是 spark 集群內節點,也可以不是,一般來說不是集群內節點,這就需要在客戶端節點上安裝程序運行所需環境,以支持 spark 的正常執行;
cluster 模式的 Driver 運行在 spark 集群中的某個 NodeManager 上,而且不確定到底是哪個 NodeManager 上,這由 spark 的調度策略決定,
如果知道了在哪個節點,在該節點上安裝程序運行所需環境即可,
但是事實是哪個節點都有可能,這意味着需要在所有節點上安裝程序運行所需環境,顯然這不是個好辦法;
隨着 application 的增加,需要不斷安裝新的包,而且不同 application 可能存在版本問題,這對於 client 模式來說或許還可以接受,但 cluster 模式肯定不行的,如果集群很大,裝環境就會死人的
一句通俗的話描述 Pyspark On Yarn:Driver 從本地電腦獲取環境后分發給 Container 來執行
問題復現
下面用一個小例子測試下 Yarn 的 模塊依賴問題
主函數
from pyspark import SparkContext from dependency.mydata import data # 自己寫的模塊 sc = SparkContext(master='yarn', appName='yilai') out = sc.parallelize(data) out.saveAsTextFile('/spark/out')
自己寫的模塊 dependency/mydata.py,這個模塊被主函數依賴
data = range(100)
運行結果
spark-submit --master yarn --deploy-mode client --py-files dep.zip mySparkCode.py # 可以執行 spark-submit --master yarn --deploy-mode cluster --py-files dep.zip mySparkCode.py # 可以執行,而且 關掉 client 可執行 spark-submit --master yarn --deploy-mode client mySparkCode.py # 可以執行 spark-submit --master yarn --deploy-mode cluster mySparkCode.py # 不可以執行
--py-files 什么意思,我后面解釋,它的作用就是把自寫模塊打包給 Driver;
在有 --py-files 的情況下,client 和 cluster 模式都可以執行,畢竟都打包上傳了,可以理解;
在沒有 --py-files 的情況下,client 模式可以運行,而且只要 dependency 放在 PYTHONPATH 的環境變量里,都可以運行,而 cluster 模式下不可執行;
原因解析
1. 被提交的任務放在 clien 端,被依賴的模塊也在 client 端
2. client 模式下,Driver 運行在 client 上,Driver 可以找到被依賴的包,並發送給 Container
3. cluster 模式下,Driver 運行在 NodeManager 上,Driver 找不到被依賴的包,報錯,Container exited with a non-zero exit code 13
而且經過我測試,自寫模塊存在鏈式依賴也可以執行,但是調用第三方模塊如 numpy 就不行了 【site-packages 下的模塊】
異常信息為
ImportError: No module named xxx
解決方案
模塊依賴也可以分為多種情景:
有簡單依賴,如單文件依賴,也有復雜依賴,如依賴多個文件,甚至 鏈式依賴,如代碼依賴 padans,而 pandas 依賴 numpy
普通依賴
普通依賴有兩種解決方法,當然這兩種方法也可以解決部分 復雜依賴 問題,是通用的方法
--py-files
它是 spark-submit 的參數,官方解釋如下
Comma-separated list of .zip, .egg, or .py files to place on the PYTHONPATH for Python apps. Comma,逗號;separated 分隔;
用逗號分隔的 zip、egg、py 文件列表來代替 PYTHONPATH 環境變量
如果依賴單個文件,直接寫文件名即可,
spark-submit --master yarn --deploy-mode cluster --py-files xxx.py mySparkCode.py
如果是多個文件,用逗號隔開,
如果是一個包,需要進行壓縮打包 【自己寫的包】
[root@hadoop10 ~]# cd /usr/lib/python27/ [root@hadoop10 python27]# ls bin dependency include lib share [root@hadoop10 python27]# zip -r dep.zip dependency/ adding: dependency/ (stored 0%) adding: dependency/__init__.py (stored 0%) adding: dependency/mydata.py (stored 0%)
效果如圖
然后執行命令
spark-submit --master yarn --deploy-mode cluster --py-files /usr/lib/python27/dep.zip mySparkCode.py
注意,壓縮文件必須是全路徑,即使它在 PYTHONPATH 環境變量內,不寫全路徑也會報錯 file do not exist
addPyFile
在代碼內部解決問題,很簡單,只需要一句
sc.addPyFile(file_path)
第三方依賴
以 numpy、pandas 為代表的第三方依賴比較麻煩,解決方案如下
1)創建 python 虛擬環境,並在虛擬環境中安裝各種需要的包
參考我的博客 python 虛擬環境
值得注意的是,可能要使用 pip install --ignore-installed 來強行安裝
2)壓縮整個虛擬環境
注意是壓縮整個環境,而不是被安裝的包
[root@hadoop10 lib]# zip -r py.zip pyspark-ml-env/
pyspark-ml-env 是虛擬環境的目錄
3)將虛擬環境壓縮包上傳 hdfs
[root@hadoop10 spark]# hadoop fs -put /usr/lib/py.zip /spark/env
4)以 numpy 為例,編寫測試代碼
import numpy as np from pyspark import SparkContext sc = SparkContext(master='yarn', appName='test_use_numpy') rdd = sc.parallelize(np.arange(100)) rdd.saveAsTextFile('/spark/numpy_test')
5)執行如下命令運行代碼
注意是 cluster 模式,client 模式不用這么麻煩
spark-submit --master yarn --deploy-mode cluster --conf spark.yarn.dist.archives=hdfs:///spark/env/py.zip#pyenv --conf spark.yarn.appMasterEnv.PYSPARK_PYTHON=pyenv/pyspark-ml-env/bin/python regression_metrics.py
spark.yarn.dist.archives:hdfs:///spark/env/py.zip 指定壓縮文件地址,壓縮文件被分發到 executor 上,並且解壓,#pyenv 代表解壓到的目錄
spark.yarn.appMasterEnv.PYSPARK_PYTHON:指定使用的 python 環境;pyenv 即上面的解壓目錄,pyspark-ml-env 即創建的虛擬環境的目錄
6)查看結果
運行正常
總結
下面我把 模塊依賴 的使用問題進行一下總結
1. Driver 負責把本地的資源分發給 Container
2. 在 client 模式下,Driver 就找在 Client 端,可以把 client 端的資源分發,而 cluster 模式下,Driver 可在集群任一節點,該節點是沒有資源的
3. 如果是 普通依賴:
在 client 模式下,Driver 可能自動收集資源,分發,無需上傳依賴;
在 cluster 模式下,Driver 無法收集資源,必須上傳依賴;
4. 如果是 復雜依賴:
在 client 模式 和 cluster 模式下,都需要通過 虛擬環境 上傳依賴
5. 在工業環境中,使用的多是 cluster 模式,cluster 模式必須上傳依賴
6. 在調試環節,多使用 client 模式,client 只需上傳復雜依賴即可
參考資料:
https://blog.csdn.net/github_38358734/article/details/78292696 講了點原理,作用不大
https://www.cnblogs.com/nucdy/p/8569606.html 和上個鏈接大同小異
https://blog.csdn.net/wangxiao7474/article/details/81391300 常規方法總結
https://zhuanlan.zhihu.com/p/43434216 知乎,說得挺詳細,此篇是我唯一實驗 numpy 等復雜依賴 成功的教程
https://www.cnblogs.com/piperck/p/10121097.html 這篇和上面 知乎 那篇雷同
https://www.jianshu.com/p/df0a189ff28b numpy 等復雜模塊的解決方案
https://www.jianshu.com/p/0787b4641b23