1. 程式人生 > 其它 >Spark詳解(04) - Spark專案開發環境搭建

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依賴

  1.     <dependencies>
  2.         <dependency>
  3.             <groupId>org.apache.spark</groupId>
  4.             <artifactId>spark-core_2.12</artifactId>
  5.             <version>3.0.0</version>
  6.         </dependency>
  7.     </dependencies>

Pom中新增打包外掛

  1.     <build>
  2.         <finalName>WordCount</finalName>
  3.         <plugins>
  4.             <plugin>
  5.                 <groupId>org.apache.maven.plugins</groupId>
  6.                 <artifactId>maven-assembly-plugin</artifactId>
  7.                 <version>3.0.0</version>
  8.                 <configuration>
  9.                     <archive>
  10.                         <manifest>
  11.                             <mainClass>com.zhangjk.WordCount</mainClass>
  12.                         </manifest>
  13.                     </archive>
  14.                     <descriptorRefs>
  15.                         <descriptorRef>jar-with-dependencies</descriptorRef>
  16.                     </descriptorRefs>
  17.                 </configuration>
  18.                 <executions>
  19.                     <execution>
  20.                         <id>make-assembly</id>
  21.                         <phase>package</phase>
  22.                         <goals>
  23.                             <goal>single</goal>
  24.                         </goals>
  25.                     </execution>
  26.                 </executions>
  27.             </plugin>
  28.         </plugins>
  29.     </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

建立伴生物件(ObjectWordCount

編寫程式碼

  1. package com.zhangjk
  2.  
  3. import org.apache.spark.rdd.RDD
  4. import org.apache.spark.{SparkConf, SparkContext}
  5.  
  6. object WordCount {
  7.   def main(args: Array[String]): Unit = {
  8.     val conf: SparkConf = new SparkConf()
  9.       //TODO 設定執行緒數,在本地idea中執行需要設定此引數,打成jar包在yarn叢集中執行需要註釋該引數設定,
  10.       .setMaster("local[*]")
  11.       .setAppName("WC")
  12.     val sc = new SparkContext(conf)
  13.     sc.setLogLevel("WARN")
  14.     val data = Array("hello scala""hello word""hello java""hello python""word count")
  15.     val inputRDD = sc.parallelize(data)
  16.     val resultRDD: RDD[(String, Int)] = inputRDD.filter(line => null != line && line.trim.length > 0)
  17.       .flatMap(_.split(" "))
  18.       .mapPartitions(iter => iter.map(_ -> 1))
  19.       .reduceByKey(_ + _)
  20.     resultRDD.coalesce(1)
  21.       .foreachPartition(
  22.         iter=>iter.foreach(println)
  23.       )
  24.     sc.stop()
  25.   }
  26. }

本地執行除錯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提交模式,即將本機當做執行環境,MasterWorker都為本機。執行時直接加斷點除錯即可

本地除錯流程

打包並提交到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之外還有其他依賴,例如zkclientkafka-clients等,此時對於不帶依賴的jar包,伺服器上也沒有對於的jar包,而帶依賴的jar包伺服器上又包含了spark依賴的所有jar包,此時在提交任務是無論提交那個jar包都不能正常執行,這是可以使用<scope>provided</scope>spark依賴的jar包在打包時忽略,這樣在WordCount-jar-with-dependencies.jarjar包中即不包含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變數