Spark-Adaptive編譯和打包

前言

spark-adaptive平時也叫做Spark自適應,這個問題也是因爲Spark3之前的版本還是比較笨的一些設置並行task數量的不合理的操作,造成資源浪費,最近是爲了需要調研嘗試,分享自己的一些過程。關於自適應的介紹,推薦一下前輩們的文章:
Spark SQL在100TB上的自適應執行實踐
Spark Adaptive Execution調研

源碼下載

操作第一步,當然就是下載源碼,github上面地址:源代碼地址
因爲那個代碼下載起來實在太慢了,我自己fork了一份在gitee上,方便我各種下載操作:
fork的地址

源碼編譯

修改倉庫地址

也是國外網絡的慢問題,我把我maven 上的setting.xml鏡像改成了阿里的源:

<mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
      <mirrorOf>central</mirrorOf>        
    </mirror>

調整JVM參數

這個是因爲maven也是一個java程序,spark的源碼還是比較龐大的,之前發現原來都fullgc了,需要調整一下jvm參數,我自己機器本身內存也比較大,調整了一下,這個控制檯執行也行,環境變量配置也行,參數如下:

export MAVEN_OPTS="-Xms12g -Xmx12g -XX:+UseG1GC"

編譯過程

spark-adaptive的項目工程和spark其實是一樣的,所以構建包也是一樣的,命令如下:

./dev/make-distribution.sh --name spark-ae-2.3 --pip --r --tgz -Psparkr -Phadoop-2.6 -Phive -Phive-thriftserver  -Pyarn -DskipTests

這裏想說明的是,後面的參數需要根據我們的需求來定義的,spark的項目可以用maven和sbt來構建,我們這種寫法是maven的做法,在源碼下面有個pom.xml文件,我們找到profile的字樣:

......
  <profile>
      <id>hadoop-2.6</id>
      <!-- Default hadoop profile. Uses global properties. -->
    </profile>
    <profile>
      <id>hadoop-2.7</id>
      <properties>
        <hadoop.version>2.7.3</hadoop.version>
        <curator.version>2.7.1</curator.version>
      </properties>
    </profile>
    <profile>
      <id>yarn</id>
      <modules>
        <module>resource-managers/yarn</module>
        <module>common/network-yarn</module>
      </modules>
    </profile>
    ......

這種結構在我們maven工程中是表示不同的環境給不同的配置,比如指定-Pyarn的時候,就會把yarn的模塊加進去,–pip其實是把python的依賴加進去,自然來說,我們是需要python環境的,r語言的依賴也是如此。大部分情況直接複製粘貼一段打包代碼,實際報錯很多也是這個原因,一方面可以去解決依賴的問題,另一方面,其實可以試着繞過我這裏的策略先不着急安裝r和python相關的模塊,所以最後的命令是:

./dev/make-distribution.sh --name spark-ae-2.3 --tgz  -Phadoop-2.6 -Phive -Phive-thriftserver  -Pyarn -DskipTests

編譯的時候其實會輸出很多中間過程信息,如果有錯誤的話需要試着去看日誌

......
+ cp -r /home/hdfs/spark-adaptive/examples/src/main /home/hdfs/spark-adaptive/dist/examples/src/
+ cp /home/hdfs/spark-adaptive/LICENSE /home/hdfs/spark-adaptive/dist
+ cp -r /home/hdfs/spark-adaptive/licenses /home/hdfs/spark-adaptive/dist
+ cp /home/hdfs/spark-adaptive/NOTICE /home/hdfs/spark-adaptive/dist
+ '[' -e /home/hdfs/spark-adaptive/CHANGES.txt ']'
+ cp -r /home/hdfs/spark-adaptive/data /home/hdfs/spark-adaptive/dist
+ '[' false == true ']'
+ echo 'Skipping building python distribution package'
Skipping building python distribution package
+ '[' false == true ']'
+ echo 'Skipping building R source package'
Skipping building R source package
+ mkdir /home/hdfs/spark-adaptive/dist/conf
+ cp /home/hdfs/spark-adaptive/conf/docker.properties.template /home/hdfs/spark-adaptive/conf/fairscheduler.xml.template /home/hdfs/spark-adaptive/conf/log4j.properties.template /home/hdfs/spark-adaptive/conf/metrics.properties.template /home/hdfs/spark-adaptive/conf/slaves.template /home/hdfs/spark-adaptive/conf/spark-defaults.conf.template /home/hdfs/spark-adaptive/conf/spark-env.sh.template /home/hdfs/spark-adaptive/dist/conf
+ cp /home/hdfs/spark-adaptive/README.md /home/hdfs/spark-adaptive/dist
+ cp -r /home/hdfs/spark-adaptive/bin /home/hdfs/spark-adaptive/dist
+ cp -r /home/hdfs/spark-adaptive/python /home/hdfs/spark-adaptive/dist
+ '[' false == true ']'
+ cp -r /home/hdfs/spark-adaptive/sbin /home/hdfs/spark-adaptive/dist
+ '[' -d /home/hdfs/spark-adaptive/R/lib/SparkR ']'
+ '[' true == true ']'
+ TARDIR_NAME=spark-2.3.2-bin-spark-ae-2.3
+ TARDIR=/home/hdfs/spark-adaptive/spark-2.3.2-bin-spark-ae-2.3
+ rm -rf /home/hdfs/spark-adaptive/spark-2.3.2-bin-spark-ae-2.3
+ cp -r /home/hdfs/spark-adaptive/dist /home/hdfs/spark-adaptive/spark-2.3.2-bin-spark-ae-2.3
**+ tar czf spark-2.3.2-bin-spark-ae-2.3.tgz -C /home/hdfs/spark-adaptive spark-2.3.2-bin-spark-ae-2.3**
+ rm -rf /home/hdfs/spark-adaptive/spark-2.3.2-bin-spark-ae-2.3

我們看到最後的部分輸出:
tar czf spark-2.3.2-bin-spark-ae-2.3.tgz -C /home/hdfs/spark-adaptive spark-2.3.2-bin-spark-ae-2.3,說明編譯好了,然後幫我們做好了打包工作;

新鮮熱乎的包就出爐了!!!

在這裏插入圖片描述

錯誤分析

我的編譯其實是很多把之後才比較順利,因爲出現問題之後我可以去解決了,我把比較有代表性的錯誤貼出來

插件和倉庫配置問題

09:39:12 [ERROR] Failed to execute goal net.alchim31.maven:scala-maven-plugin:3.2.2:compile (scala-compile-first) on project spark-tags_2.12: Execution scala-compile-first of goal net.alchim31.maven:scala-maven-plugin:3.2.2:compile failed: A required class was missing while executing net.alchim31.maven:scala-maven-plugin:3.2.2:compile: xsbt/Analyzer$

出現錯誤的時候我們第一件事就是需要淡定,maven編譯的錯誤比較隱晦,這個錯誤表面是類依賴找不到的問題,實際上就是插件依賴有問題。
根本原因就是,spark是scala和java混合方式的打包的,scala的代碼需要專門的插件去做這個工作,一開始並不會在你倉庫裏面有,沒有就需要去下載,我們找到maven配置倉庫下載插件地址的地方,這個其實是一箇中央倉庫:

  <pluginRepositories>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </pluginRepository>
  </pluginRepositories>

因爲在國內來說,我們的網絡情況其實不大穩定的,有些插件下載不過來,當出現類似插件問題的時候,我們首先需要保證插件可以被正確下載到。解決辦法也比較直接,改成阿里倉庫或者公司內部倉庫就可以了。在setting.xml或者pom.xml裏面加都是可以的。

<pluginRepositories>
  	<pluginRepository>
              <id>alimaven</id>
              <name>central</name>
              <url>http://maven.aliyun.com/nexus/content/repositories/central</url>         
          </pluginRepository>
  </pluginRepositories>

scala版本問題

再來一個,類似類找不到的問題

10:11:38 [error] /home/jenkins/workspace/spark-adaptive/common/unsafe/src/test/scala/org/apache/spark/unsafe/types/UTF8StringPropertyCheckSuite.scala:96: exception during macro expansion: 
10:11:38 [error] java.lang.NoClassDefFoundError: scala/runtime/LazyRef
10:11:38 [error] 	at org.scalactic.MacroOwnerRepair$Utils.repairOwners(MacroOwnerRepair.scala:66)
10:11:38 [error] 	at org.scalactic.MacroOwnerRepair.repairOwners(MacroOwnerRepair.scala:46)
10:11:38 [error] 	at org.scalactic.BooleanMacro.genMacro(BooleanMacro.scala:837)
10:11:38 [error] 	at org.scalatest.AssertionsMacro$.assert(AssertionsMacro.scala:34)
10:11:38 [error]         assert(toUTF8(s).contains(toUTF8(substring)) === s.contains(substring))
10:11:38 [error] 

這個也要去分析,scala/runtime/LazyRef這種runtime基礎的類其實是自帶的類庫,自帶的類庫都找不到了,我們這個時候要懷疑scala版本的問題,spark編譯的時候其實也知道這個事情,所以做了個切換scala版本的腳本,我們需要在執行編譯之前再執行下面這個腳本,做一個切換動作。

./dev/change-scala-version.sh 2.11

當然,我們需要知道爲啥找不到,這個其實是因爲我們用scala2.12的時候,需要指定maven庫中的依賴scala版本也要變化,我們找到pom.xml 2723行左右,我們找到scala版本的定義地方:

<!-- Exists for backwards compatibility; profile doesn't do anything -->
    <profile>
      <id>scala-2.11</id>
    </profile>
    <profile>
      <id>scala-2.12</id>
      <properties>
        <scala.version>2.12.4</scala.version>
        <scala.binary.version>2.12</scala.binary.version>
      </properties>
      ......
    </profile>

我們的maven是可以通過-p參數來切換版本的,所以我們主動加上-Pscala-2.12新的版本纔會生效,大致就是說你要切版本,全部都要一套下來纔行!!一條龍走下去就會順當很多了。

外部依賴的問題

其他的情況比較多的就是外部依賴了,我們的-pip -r這類參數,其實就是需要環境裏面有相應的命令,編譯的時候maven會像糖葫蘆一樣把各個命令串起來,到了pyhon的時候會去用pip拉取一些python相關的包,r也是如此,那麼這個時候需要自己先按照包了,比如python的情況提前加一個這個:

sudo pip install wheel

r的話需要離線安裝r的包,整套就會出來的!
切記冷靜分析,百度上的信息不是很好找,需要找到根本原因再去解決,纔是上上策~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章