IDEA開發Spark應用並提交本地Spark 2.1.0 stand
一、透過IDEA連線遠端叢集執行應用就是個大坑。。
寫在2017年10月3日凌晨0點57分:
最初這篇博文的名字是“IDEA開發Spark應用並提交遠端Spark 2.1.0 standalone叢集執行”,當時以不能SSH免密碼登入遠端主機為由,直接連線本地叢集執行應用,後來又嘗試了一下透過IDEA連線部署在實驗室伺服器上的Spark叢集來執行應用,然後就發現這裡實在是坑太多。如果部署模式是“client”,則會在本地主機起一個driver程式,而從本地主機序列化分發jar包到叢集各從節點要求本地主機能夠SSH免密碼登入各從節點!!(當然執行時只需要網路互通即可)如果部署模式是“cluster”,然後IDEA執行項裡配置“VM options”為-Dspark.submit.deployMode=cluster,結果很不幸,driver依然在本機執行,然後執行器和驅動器無法互相通訊。
透過spark-submit指令碼,設定部署模式為cluster,這樣driver會在某一個worker上啟動,然而我們的jar包依然在本機,還是需要序列化分發到各節點,然而這樣就需要本地主機可以免密碼SSH登入所有叢集節點!!
當然本地開發測試還是可以透過IDEA連線本地叢集執行應用,畢竟藉助IDEA,我們只需點一下“執行”即可,還是方便很多。所以啊,本文決定把題目和內容改一下,把遠端改成本地!
二、前言
雖然之前也有許多博文講如何基於IDEA來開發執行Spark應用,但是他們大多數都以本地模式執行(例如:conf.setMaster("local[*]")),而本地模式只是在本機以多執行緒方式執行Spark應用,這與standalone模式執行有很大差別。
此外,雖然也有一些博文介紹瞭如何使用IDEA將開發的Spark應用提交到本地Spark叢集執行,但是這些博文涉及的Spark版本都比較老,較新版本的Spark(例如2.1.0及以後)取消了lib目錄,也就是說新版本沒有assembly jar包(例如:spark-assembly-1.5.2-hadoop2.6.0.jar),取而代之的是jars目錄,這就使得在新版本里,依賴包的新增發生了一些變化。
綜上所述,還是很有必要重新寫一篇關於IDEA提交Spark應用到本地叢集的博文,這篇博文關注點在於如何讓IDEA連線Spark 2.1.0 standalone叢集。
這篇博文首先介紹了幾種Spark應用開發和執行的方式,然後介紹瞭如何透過IDEA連線Spark standalone叢集來開發執行Spark應用,最後對可能發生的錯誤給出瞭解決方法。
注意:由於大部分情況下,我們不能隨意訪問遠端主機,例如不能直接ssh免密碼登入遠端主機,所以本文只是將IDEA連線到了本機的Spark 2.1.0 standalone叢集,也就是將Spark應用提交到本地叢集執行。
三、開發環境
作業系統:CentOS 7
Spark:2.1.0
IDEA:社群版2016.3.1
Scala:2.11.8
JDK:1.8.0_111
四、Spark應用開發執行綜述
1、開發
用Scala開發Spark應用,官方推薦使用SBT專案構建工具,當然由於Scala基於JVM,所以使用Maven也是可以的。有時我們想在專案中混合使用Java和Scala,這時Maven就成了最佳選擇,當然這個時候就需要在pom.xml中配置Java和Scala的編譯工具。
可以純粹使用專案構建工具SBT或者Maven來完成Spark開發(不借助IDE),包括按照模板建立專案、編譯、構建專案、打包和釋出等等。當然也可以藉助IDEA整合的SBT和Maven外掛來高效完成上述工作(IDE+專案構建工具)。
當然這篇博文只使用IDEA來完成上述工作,沒有使用專案構建工具。
2、執行
開發完專案後當然就要執行我們的Spark應用了,執行也有好幾種方式。
(1)第一種方式主要用於開發測試完畢,準備線上執行。藉助IDEA或者使用專案構建工具將Spark應用打成Jar包,接著上傳到伺服器(windows使用FileZilla,Linux使用scp命令),然後透過spark-submit指令碼連線叢集(透過master的URL可以連線到不同叢集)並執行Spark應用。
(2)第二種方式是本地測試。打包後直接提交本地Spark standalone叢集(偽分散式,本機執行master和worker)。
(3)開發時會頻繁地執行Spark應用,前面兩種方式就顯得比較麻煩(需要打包、上傳、提交),第三種方式用於開發過程中。透過IDEA連線Spark standalone叢集,只需點選IDEA的“執行”按鈕即可執行Spark應用(不需要手動打包,不需要上傳到伺服器,不需要手動執行spark-submit指令碼)。當然也可以以local模式執行(可以在應用程式中使用conf.setMaster("local[*]")或者在IDEA執行項中配置“VM options”為-Dspark.master=local[*],然後點選IDEA的“執行”按鈕),此時在本地以多執行緒方式執行Spark應用,local模式不需要開啟Spark叢集。
下面介紹如何透過IDEA連線Spark standalone叢集,來快速開發除錯Spark應用。
五、透過IDEA將開發的Spark應用提交到本地Spark 2.1.0 standalone叢集執行
1、前提要求(版本資訊見“開發環境”)
(1)需要有一個Spark standalone叢集,不需要hdfs,能啟動執行即可。
(2)IntelliJ IDEA、Scala外掛、Java JDK、Scala SDK都已安裝配置完畢。
2、建立專案
新建一個Scala專案。啟動IntelliJ IDEA,選擇New Project,然後選擇Scala,點選下一步,接著配置專案名稱、SDK版本和專案位置等。注意:IDEA中專案的概念類似於Eclipse中的工作區(workspace),而IDEA中模組(module)的概念類似於Eclipse中的專案。
圖1 新建一個Scala專案
圖2 配置專案(名稱、SDK和位置等)
3、新增依賴的Jar包
如前文所述,較新版本的Spark(例如2.1.0及以後)取消了lib目錄,取而代之的是jars目錄,所以這裡依賴包的新增相比於舊版本發生了一些變化。
首先按如下步驟(圖3、圖4和圖5)為我們開發的Spark應用新增依賴,把Spark 2.1.0中的jars目錄整個新增進來(這樣jars目錄裡所有的jar包都會被新增到classpath中),並調整它的scope為“編譯”(這樣我們後面打的包會包括jars目錄裡所有的jar包)。
看到這裡,讀者可能會心生疑惑,我們開發的應用事實上用不著這麼多的jar包,例如關於機器學習或者流計算的jar包我們肯定用不上,另外,這些jar包Spark叢集中都有,為什麼還要把scope設為“編譯”呢?
如果是手動打包然後透過spark-submit指令碼執行應用的話,確實只需新增幾個jar包即可,而且scope還應該設為“provided”,這樣可以減少最終生成jar包的大小。然而透過IDEA提交Spark應用到本地叢集,還就必須按前述步驟做,否則會報java.lang.NoClassDefFoundError的錯誤(不把整個jars目錄新增到classpath中會報錯,不把它的scope設為“編譯”也會報錯)。
java.lang.ClassNotFoundException和java.lang.NoClassDefFoundError這兩種錯誤看起來有點像,但它們是完全不同的。NoClassDefFoundError是指JVM執行時無法在classpath中找到對應的類進行載入;而ClassNotFoundException是指編譯的時候classpath中找不到對應的類。
圖3 為Spark應用新增依賴
圖4 把Spark 2.1.0中的jars目錄整個新增進來
圖5 調整scope為“編譯”
4、完成程式碼
在src目錄下新建一個名為WordCount的object,這是我們的main class。接著在原始檔中輸入Spark的HelloWorld程式——WordCount。因為這裡連線的是本地Spark 2.1.0 standalone叢集,所以直接從本地讀取檔案。
有兩點需要注意:
(1)因為要提交Spark應用到本地叢集執行,所以需要配置master的URL,可以在應用程式中使用conf.setMaster("spark://host:port")或者在IDEA執行項中配置“VM options”為-Dspark.master=spark://host:port,“host”就是master所在的主機名,如果沒有在/etc/hosts中建立主機名和IP的對映關係,則直接使用IP。
(2)透過conf.setJars(List("/path/to/xxx.jar")),告訴Spark叢集我們要提交的包含作業程式碼的jar包在哪裡,記住路徑中千萬別包含中文,不然會出錯。
圖6 在src目錄下新建WordCount.scala
圖7 輸入WordCount程式碼
5、配置打包
即便是透過IDEA提交Spark應用到本地叢集執行,我們還是需要配置打包。Spark應用之所以能夠分散式執行,正是因為jar包被分發到了各個worker之中。
我們將應用程式打成可執行jar包,併為它設定main class,然後再把“構建專案自動打包”的選項勾上,這樣才能做到點選“執行”就提交到本地叢集執行。
圖8 將Spark應用打包
圖9 可執行jar包,配置main class
圖10 構建專案時自動打包
6、配置IDEA執行項
這裡結合spark-submit指令碼,說明一下IDEA是怎麼做到一鍵提交Spark應用到本地叢集執行。當我們點選“執行”按鈕,IDEA會自動構建專案,並重新打包;然後根據應用程式中的conf.setJars(List("/path/to/xxx.jar")),可以找到需要提交到叢集的jar包;根據conf.setMaster("spark://host:port")或者IDEA執行項中“VM options”的-Dspark.master=spark://host:port連線到Spark standalone叢集,這相當於配置spark-submit指令碼的--master;然後IDEA執行項中的“Main class”指定了Spark應用的main class,這相當於配置spark-submit指令碼的--class;如果還想為Spark應用做一些其他配置,可以透過conf.set("xxx", "XXX")或者“VM options”新增一些其他配置(形如-Dxxx.yyy=zzz);傳給Spark應用main方法的引數在“Program arguments”中輸入。
所以使用IDEA連線叢集,透過IDEA將Spark應用提交本地叢集執行,其實就是IDEA替我們完成了打包和執行spark-submit指令碼的工作。
圖11 配置IDEA執行項
7、啟動Spark叢集
在點選“執行”按鈕之前,需要確保目標本地Spark standalone叢集已經啟動。
注意:我們開發時使用的Spark版本要和本地叢集一致。
8、執行,觀察IDEA控制檯結果,觀察Spark Web UI。
終於到了最後一步,點選“執行”按鈕,見證奇蹟吧(2333333......)。
可以看到,控制檯成功輸出了詞頻統計。也可以開啟Spark Web UI,詳細看一下應用執行情況。
圖12 控制檯輸出結果
圖13 Spark Web UI檢視應用詳細執行情況
六、可能出現的錯誤
1、可能會出現如下錯誤:建立SparkContext時出現異常
java.net.BindException: Cannot assign requested address: Service 'sparkDriver' failed after 16 retries (starting from 0)! Consider explicitly setting the appropriate port for the service 'sparkDriver '(for example spark.ui.port for SparkUI) to an available port or increasing spark.port.maxRetries.
解決方法:在IDEA執行項“VM options”中加入“-Dspark.driver.host=127.0.0.1”和“-Dspark.driver.port=7077” 這兩項, 配置driver程式在本機的7077埠執行。
2、還可能出現這個錯誤:Hadoop許可權錯誤
org.apache.hadoop.security.AccessControlException: Permission denied: user=yourUsername, access=WRITE, inode="/user/otherUsername/":otherUsername:supergroup:drwxr-xr-x
這是因為,HDFS中每個使用者都有自己的home目錄(與Linux系統一致),使用者自己的目錄只有該使用者擁有寫許可權,遠端連線Spark叢集執行應用時,若使用本機使用者嘗試對其他使用者在HDFS中的home目錄進行寫操作,會出現這個問題。
解決辦法:
(1)修改Hadoop 配置檔案hdfs-site.xml,設定dfs.permissions.enabled為false即可,這樣不會再有許可權限制,具體如圖14所示。當然,開發測試完了最好還是把這個許可權限制機制開啟。
圖14 修改Hadoop配置檔案hdfs-site.xml
(2)使用和遠端叢集一致的使用者,或者在同名使用者home目錄下進行寫操作。
轉載請註明如下內容:
文章來自簡書,作者:就是楊宗
原文連結:
作者:就是楊宗
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3549/viewspace-2818777/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- IDEA開發Spark應用實戰(Scala)IdeaSpark
- spark 2.1.0 standalone模式配置&&打包jar包透過spark-submit提交Spark模式JARMIT
- Spark RDD的預設分割槽數:(spark 2.1.0)Spark
- 【spark筆記】在idea用maven匯入spark原始碼Spark筆記IdeaMaven原始碼
- 使用Intellij Idea編寫Spark應用程式(Scala+SBT)IntelliJIdeaSpark
- Spark2.4.5叢集安裝與本地開發Spark
- Spark之HiveSupport連線(spark-shell和IDEA)SparkHiveIdea
- Spark應用程式開發引數調優深入剖析-Spark商業調優實戰Spark
- 第一個spark應用開發詳解(java版)SparkJava
- spark在IDEA的本地無法使用saveAsTextFile儲存檔案SparkIdeaAST
- 01-Spark的Local模式與應用開發入門Spark模式
- spark-submit 提交的引數SparkMIT
- Spark面試題(七)——Spark程式開發調優Spark面試題
- Spark 從零到開發(五)初識Spark SQLSparkSQL
- Spark入門(二)--如何用Idea執行我們的Spark專案SparkIdea
- spark 原始碼分析之十九 -- Stage的提交Spark原始碼
- Docker中提交任務到Spark叢集DockerSpark
- spark原始碼之任務提交過程Spark原始碼
- 大資料開發-Spark-初識Spark-Graph && 快速入門大資料Spark
- Spark core 寫程式 指定 本地或者hdfsSpark
- Spark之spark shellSpark
- 使用Intellij IDEA遠端除錯Spark程式IntelliJIdea除錯Spark
- spark核心(下)——job任務提交原始碼解析Spark原始碼
- Spark 效能調優--開發階段Spark
- spark 基礎開發 Tips總結Spark
- 基於RDD的Spark應用程式開發案列講解(詞頻統計)Spark
- Spark系列 - (3) Spark SQLSparkSQL
- Spark on Yarn 和Spark on MesosSparkYarn
- 提交Spark作業遇到的NoSuchMethodError問題總結SparkError
- Spark學習進度-Spark環境搭建&Spark shellSpark
- 【Spark】Spark容錯機制Spark
- Spark 開窗函式Spark函式
- sparkSpark
- IDEA WordCount jar包上傳spark除錯及排錯IdeaJARSpark除錯
- Spark原始碼編譯與匯入IDEA除錯Spark原始碼編譯Idea除錯
- Spark 原始碼解析 : DAGScheduler中的DAG劃分與提交Spark原始碼
- Spark記錄(一):Spark全景概述Spark
- Spark 系列(十四)—— Spark Streaming 基本操作Spark