Spark詳解(04) - Spark專案開發環境搭建
類別 [隨筆分類]Spark
Spark詳解(04) - Spark專案開發環境搭建
Spark Shell僅在測試和驗證程式時使用的較多,在生產環境中,通常會在IDEA中編制程式,然後打成Jar包,提交到叢集,最常用的是建立一個Maven專案,利用Maven來管理Jar包的依賴。
新建專案
在idea中file — new project,選擇Maven
填寫gid和aid
下一步點選next
選擇專案名以及專案原始碼儲存路徑,點選Finish
建立完成後會自動開啟pom.xml頁面
配置環境
配置Maven
選擇本地maven路徑:file – settings
新增scala的lib和SDK:file – project structure
新增成功後在External Libraries下顯示scala-sdk
使用maven新增依賴包
本地新增方式和maven方式二者選一即可
在pom中新增spark依賴
- <dependencies>
- <dependency>
- <groupId>org.apache.spark</groupId>
- <artifactId>spark-core_2.12</artifactId>
- <version>3.0.0</version>
- </dependency>
- </dependencies>
Pom中新增打包外掛
- <build>
- <finalName>WordCount</finalName>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <version>3.0.0</version>
- <configuration>
- <archive>
- <manifest>
- <mainClass>com.zhangjk.WordCount</mainClass>
- </manifest>
- </archive>
- <descriptorRefs>
- <descriptorRef>jar-with-dependencies</descriptorRef>
- </descriptorRefs>
- </configuration>
- <executions>
- <execution>
- <id>make-assembly</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
離線新增本地spark的依賴jar包:file – project structure
本地新增方式和maven方式二者選一即可
這裡新增spark jar包是為了方便本地開發環境執行saprk任務方便除錯,可以從本地安裝的spark環境中選擇,也可以使用maven新增,選擇本地檔案更方便管理,因為在提交spark任務到yarn叢集時由於yarn叢集中已經有spark相關依賴,所以在專案打包時需要將spark依賴去掉(不去掉spark任務會執行失敗),同時spark之外的其他依賴打包時又不能去掉。本地spark jar包新增完成後會在External Libraries下顯示。
除了spark依賴的jar,專案需要的其他依賴可以在pom中新增其他依賴通過maven管理
- 新增其他依賴包
Spark專案中除了spark相關依賴包外的其他依賴包還是需要在打包時放到jar包中的,
在pom.xml中新增相關依賴
file – project structure
從這裡可以看到,spark相關依賴包都在jars目錄中,而maven管理的jar包都直接顯示出來,所以spark的相關依賴可以選擇不使用maven管理
重新bulid專案即可
如果jar包在yarn平臺中執行時報 java.lang.ClassNotFoundException: org.ansj.recognition.impl.StopRecognition
意思是程式找不到maven引入的依賴,使用壓縮軟體開啟jar包如下
發現只有自己編寫的程式碼是以檔案加在jar包中,而引入的jar包則是以jar檔案的方式在壓縮包中
解決方法如下
使用壓縮軟體將jar包解壓
然後將不是依賴包的目錄檔案刪除
然後將所有依賴的jar包再次解壓到當前資料夾
最有將解壓後的依賴jar包在壓縮到原有的jar包檔案中
這樣在重新提交任務就不會出現找不到類的錯誤了
這是一種解決方案,ieda在打包時應該可以設定依賴包的打包方式,若有知道的請告知
建立scala原始碼包
Main目錄下建立scala目錄:在main目錄上右鍵單擊
將建立的scala目錄轉成根目錄,在上一步建立的scala目錄右鍵單擊
編寫wordcount測試程式
在scala目錄下新建包名:com.zhangjk
建立伴生物件(Object)WordCount
編寫程式碼
- package com.zhangjk
- import org.apache.spark.rdd.RDD
- import org.apache.spark.{SparkConf, SparkContext}
- object WordCount {
- def main(args: Array[String]): Unit = {
- val conf: SparkConf = new SparkConf()
- //TODO 設定執行緒數,在本地idea中執行需要設定此引數,打成jar包在yarn叢集中執行需要註釋該引數設定,
- .setMaster("local[*]")
- .setAppName("WC")
- val sc = new SparkContext(conf)
- sc.setLogLevel("WARN")
- val data = Array("hello scala", "hello word", "hello java", "hello python", "word count")
- val inputRDD = sc.parallelize(data)
- val resultRDD: RDD[(String, Int)] = inputRDD.filter(line => null != line && line.trim.length > 0)
- .flatMap(_.split(" "))
- .mapPartitions(iter => iter.map(_ -> 1))
- .reduceByKey(_ + _)
- resultRDD.coalesce(1)
- .foreachPartition(
- iter=>iter.foreach(println)
- )
- sc.stop()
- }
- }
本地執行除錯spark程式碼
- 檢查Spark版本和scala版本是否一致
使用IDEA工具執行執行spark專案時必須保證spark依賴的scala版本和本地安裝的版本保持一致,如果不一致會報如下錯誤
Exception in thread "main" java.lang.NoSuchMethodError: scala.Product.$init$(Lscala/Product;)V
如果確定spark版本和scala版本是否一致
在cmd中執行spark-shell,可以看到spark-3.0.0版本使用的scala版本是2.12.10
在另一個cmd中輸入scala命令可以看到當前使用的scala執行環境是2.12.10,和spark要求的一致,如果不一致,則需要下載對應版本的scala環境安裝包重新安裝
- 本地執行除錯
本地Spark程式除錯需要使用Local提交模式,即將本機當做執行環境,Master和Worker都為本機。執行時直接加斷點除錯即可
本地除錯流程
打包並提交到yarn平臺執行
打包
- 使用artifacts打包
新建build
選擇執行的主類
無論是否指定都需要在提交spark任務時使用--class com.taiji. WordCount引數設定jar包執行的主類
若出現下面的錯誤,刪除MANIFEST.MF
由於spark程式部分依賴包伺服器上已有,需要手工將spark的相關依賴jar包刪除。
如果是新建專案,並且按照上面的方式新增的spark依賴,把所有的都刪除,只保留最後一個,然後再按照專案需要再pom中新增其他依賴
儲存配置
編譯打包
最終生產的jar包
- 使用maven打包
在maven控制檯點選package打包,
然後,檢視打完後的jar包
其中:
WordCount.jar是不帶依賴的jar包,在提交任務時,由於伺服器上已經安裝了spark的相關依賴,一般會使用該jar包
WordCount-jar-with-dependencies.jar是帶所有依賴的jar包
如果spark程式中引入的依賴除了spark-core之外還有其他依賴,例如zkclient、kafka-clients等,此時對於不帶依賴的jar包,伺服器上也沒有對於的jar包,而帶依賴的jar包伺服器上又包含了spark依賴的所有jar包,此時在提交任務是無論提交那個jar包都不能正常執行,這是可以使用<scope>provided</scope>將spark依賴的jar包在打包時忽略,這樣在WordCount-jar-with-dependencies.jar的jar包中即不包含saprk依賴又還有其他依賴
提交任務
使用spark-submit提交任務,需要注意使用者許可權,如果是cdh安裝的yarn平臺,需要切換到spark或hdfs使用者執行submit命令 同時存放jar包的目錄儘量具有777的許可權
如果使用spark 有時候需要訪問hdfs檔案系統,spark使用者也會受到許可權限制,這時可以切換到hdfs使用者試試
在命令前面新增nohup是後臺方式執行,不加即為前臺方式啟動,連線終端斷開任務即停止執行
- 提交spark任務到yarn平臺
把jar包上傳到伺服器/opt/module/spark-yarn目錄
執行submit命令
[hadoop@hadoop102 spark-yarn]$ bin/spark-submit --class com.zhangjk.WordCount --master yarn ./WordCount.jar
- spark-submit 詳細引數說明
--master master 的地址,提交任務到哪裡執行,例如 spark://host:port, yarn, local
--deploy-mode 在本地 (client) 啟動 driver 或在 cluster 上啟動,預設是 client
--class 應用程式的主類,僅針對 java 或 scala 應用
--name 應用程式的名稱
--jars 用逗號分隔的本地 jar 包,設定後,這些 jar 將包含在 driver 和 executor 的 classpath 下
--packages 包含在driver 和executor 的 classpath 中的 jar 的 maven 座標
--exclude-packages 為了避免衝突 而指定不包含的 package
--repositories 遠端 repository
--conf PROP=VALUE 指定 spark 配置屬性的值,例如 -conf spark.executor.extraJavaOptions="-XX:MaxPermSize=256m"
--properties-ile 載入的配置檔案,預設為 conf/spark-defaults.conf
--driver-memory Driver記憶體,預設 1G
--driver-java-options 傳給 driver 的額外的 Java 選項
--driver-library-path 傳給 driver 的額外的庫路徑
--driver-class-path 傳給 driver 的額外的類路徑
--driver-cores Driver 的核數,預設是1。在 yarn 或者 standalone 下使用
--executor-memory 每個 executor 的記憶體,預設是1G
--total-executor-cores 所有 executor 總共的核數。僅僅在 mesos 或者 standalone 下使用
--num-executors 啟動的 executor 數量。預設為2。在 yarn 下使用
--executor-core 每個 executor 的核數。在yarn或者standalone下使用
其他常用
關聯原始碼
按住ctrl鍵,點選RDD
提示下載或者繫結原始碼
解壓資料包中spark-3.0.0.tgz到非中文路徑。
點選Attach Sources…按鈕,選擇原始碼路徑
建立IDEA快捷鍵
1)點選File->Settings…->Editor->Live Templates->output->Live Template
2)點選左下角的Define->選擇Scala
3)在Abbreviation中輸入快捷鍵名稱scc,在Template text中填寫,輸入快捷鍵後生成的內容。
//1.建立SparkConf並設定App名稱
val conf: SparkConf = new SparkConf().setAppName("SparkCoreTest").setMaster("local[*]")
//2.建立SparkContext,該物件是提交Spark App的入口
val sc: SparkContext = new SparkContext(conf)
//4.關閉連線
sc.stop()
異常處理
idea打jar包缺少class檔案(classes目錄為空)
將打好的jar包上傳到伺服器上提交任務時發現報Error: Failed to load class錯誤,日誌如下:
2022-03-13 02:29:38,620 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Error: Failed to load class com.zhangjk.WordCount.
2022-03-13 02:29:38,763 INFO util.ShutdownHookManager: Shutdown hook called
2022-03-13 02:29:38,764 INFO util.ShutdownHookManager: Deleting directory /tmp/spark-35dd8e48-28ec-4ca7-a8ee-45b3eeb0f49e
通過壓縮軟體開啟jar包,發現根本找不到classes目錄及class檔案
在IDEA中發現打包結果的classes目錄也為空:
解決方案
現在idea中執行一次專案
執行成功後。
此時target目錄下的classes目錄出現了對應的class檔案:
再次點選maven的package命令打包,將打好的jar包再次使用壓縮軟體開啟,可以看到對於的class檔案出現了
出現這種情況是因為某些原因導致package命令打包不能自動編譯。在idea中執行專案會先編譯,然後在打包就能把編譯後的檔案打到jar包中了
缺少Hadoop
如果本機作業系統是Windows,如果在程式中使用了Hadoop相關的東西,比如寫入檔案到HDFS,則會遇到如下異常:
出現這個問題的原因,並不是程式的錯誤,而是用到了Hadoop相關的服務,解決辦法
1)配置HADOOP_HOME環境變數
2)在IDEA中配置Run Configuration,新增HADOOP_HOME變數