先拋出問題:Spark on Yarn有cluster和client兩種模式,它們有什麼區別? 用Jupyter寫Spark時,只能使用client模式,爲何?html
寫一篇文章,搞清楚 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,這裏先無論它。)oop
總結起來就是:Spark是一套能夠運行的代碼,代碼運行須要資源(計算、存儲、網絡),Yarn把集羣的資源分配一部分給Spark使用。spa
Yarn自己的運行方式是:Yarn把集羣的節點分爲兩類,一類是Master,運行的進程叫ResourceManager(簡稱RM),另外一類是Worker,運行的進程叫NodeManager(簡稱NM),NM能夠在本機內分配資源,生成若干個Container(不熟悉容器的同窗能夠把Container近似理解爲虛擬機)。Yarn的運行過程是,RM接受外部的資源申請(能夠來自Hadoop、Spark或其餘進程),按照要求分配資源,而後把對應的資源分配計劃通知各個NM,NM收到本身的分配計劃,按計劃在本地啓動若干個Container。code
Spark和Yarn各自介紹完畢。htm
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 就結合起來了。blog
這裏給出一個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