前言
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的包,整套就會出來的!
切記冷靜分析,百度上的信息不是很好找,需要找到根本原因再去解決,纔是上上策~~