先抛出問題:Spark on Yarn有cluster和client兩種模式,它們有什麼差別? 用Jupyter寫Spark時,隻能使用client模式,為什麼?
寫一篇文章,搞清楚 Spark on Yarn 的運作原理,同時回答上面的問題。
首先,把Spark和Yarn當做兩個獨立概念來看。單看Spark,不去管它底層依賴的存儲結構,本質上講,它就是個分布式計算的程式。程式的入口是一個叫做 SparkContext 的對象,也可以抽象地稱為Driver,啟動了 SparkContext 後,就可以運作各種Spark方法(比如 map,filter)。運作方法時,Spark會把每次執行分解成若幹個Task,分發給若幹個Executor執行,Executor是執行Task的程序,執行後的結果彙總到一起,傳回給 SparkContext。Spark 本質上也是一個map+reduce的過程,與Hadoop不同的是,Spark會先把資料存儲到記憶體中,這樣處理速度會比Hadoop快大約兩個數量級。
這麼多的Executor程序是怎麼來的?
是Yarn配置設定的。(注:還有其他資源管理架構,比如 Moses,這裡先不管它。)
總結起來就是:Spark是一套可以運作的代碼,代碼運作需要資源(計算、存儲、網絡),Yarn把叢集的資源配置設定一部分給Spark使用。
Yarn本身的運作方式是:Yarn把叢集的節點分為兩類,一類是Master,運作的程序叫ResourceManager(簡稱RM),另一類是Worker,運作的程序叫NodeManager(簡稱NM),NM可以在本機内配置設定資源,生成若幹個Container(不熟悉容器的同學可以把Container近似了解為虛拟機)。Yarn的運作過程是,RM接受外部的資源申請(可以來自Hadoop、Spark或其他程序),按照要求配置設定資源,然後把對應的資源配置設定計劃通知各個NM,NM收到自己的配置設定計劃,按計劃在本地啟動若幹個Container。
Spark和Yarn各自介紹完畢。
Spark on Yarn就是把上述過程結合起來,Yarn在底層,Spark在上層,也就是說,我們在寫Spark代碼時不需要操作Yarn,隻需要設定好Spark的資源參數,Yarn會按照Spark的資源參數去配置設定資源,然後提供給Spark使用。
Spark on Yarn 的運作過程是:SparkContext運作起來,設定資源參數,Yarn中會為每個Spark App啟動一個Container,叫做App Master,由App Master把資源參數發送給RM,RM通知若幹個NM,啟動若幹個Container,每個Container内部都運作一個Executor,對,就是Spark中的Executor,這樣Spark 和 Yarn 就結合起來了。
這裡給出一個Spark on Yarn的資源參數配置示例:
conf = SparkConf().setMaster('yarn-client').setAppName('test')
conf.set('spark.executor.instances',10)
conf.set('spark.executor.cores',1)
conf.set('spark.executor.memory','2g')
conf.set("spark.driver.memory", "2g")
conf.set("spark.driver.maxResultSize", "0")
Spark on Yarn的原理都清楚了,下面要解決開頭提出的問題了:Spark on Yarn 的 cluster 和 client 模式有什麼差別?為什麼Jupyter隻能用client模式?
對比cluster和client,從名字就可以看出,前者是分布式的,後者是本地化的。具體差別就在于上面的紅字:App Master的作用不同。
在cluster模式中,SparkContext運作在App Master所在的Container中,也就是說,在初始化Spark程式時,我們不知道SparkContext會運作在哪個節點,由RM配置設定一個Container作為App Master後,SparkContext運作在這個Container中,Spark程式的運作與我們在哪個節點啟動它沒有關系。
相對地,在client模式中,SparkContext運作在啟動SparkContext的節點上,所有與Spark有關的排程工作都在這個節點上運作(注意:不是在這個節點的Container上),App Master隻在向RM申請資源時起到了作用,之後就它什麼事了,除非資源需要發生變化。
到這裡,我們就能明白為什麼Jupyter必須使用client模式了,因為Jupyter是運作在節點上的程序,隻能和本地節點的記憶體實作資料互動,為了能夠擷取到spark運作過程中的變量,Jupyter必須采用Client模式,讓spark程式的變量值存儲在節點的記憶體中。
參考資料:
https://www.cnblogs.com/tgzhu/p/5818374.html
轉載于:https://www.cnblogs.com/xxiaolige/p/9257745.html