如何為Spark Application指定不同的JDK版本詳解
前言
隨著企業(yè)內(nèi)部業(yè)務(wù)系統(tǒng)越來(lái)越多,基于JVM的服務(wù),通常情況線上環(huán)境可能會(huì)有多套JDK跑不同的服務(wù)。大家都知道基于高版本的Java規(guī)范編寫的服務(wù)跑在低版本的JVM上會(huì)出現(xiàn):java.lang.UnsupportedClassVersionError
的異常。
Spark 2.2開(kāi)始移除了對(duì)Java 7的支持,大多數(shù)情況下,我們的Spark Application是和Hadoop系統(tǒng)公用的JDK,如果Hadoop依賴的JDK版本是7,那我們基于JDK 8編寫的Application跑在上面就會(huì)出問(wèn)題。
該文主要介紹在不同的場(chǎng)景下,如何為Spark Application指定不同的JDK版本。
集群已部署了指定的JDK版本
假設(shè)集群中每個(gè)節(jié)點(diǎn)JDK的部署路徑為:/usr/java/jdk1.8
Spark提供了spark.executorEnv.[EnvironmentVariableName]
配置,可以用來(lái)給Executor進(jìn)程添加環(huán)境變量,如果Spark Application使用的集群管理器是Standalone,只需要通過(guò)spark.executorEnv.JAVA_HOME
制定Executor端的jdk路徑即可,如下:
$SPARK_HOME/bin/spark-submit \ --conf "spark.executorEnv.JAVA_HOME=/usr/java/jdk1.8" \ ...
在YARN模式下,還需要為Application Master指定不同的JAVA_HOME環(huán)境變量,如下:
$SPARK_HOME/bin/spark-submit \ --conf "spark.executorEnv.JAVA_HOME=/usr/java/jdk1.8" \ --conf "spark.yarn.appMasterEnv.JAVA_HOME=/usr/java/jdk1.8" \ ...
以cluster的方式部署在YARN上的時(shí)候,spark.yarn.appMasterEnv.JAVA_HOME
相當(dāng)于為Spark Application的Driver設(shè)置了特定的JDK版本;
以client的模式部署時(shí),spark.yarn.appMasterEnv.JAVA_HOME
僅僅是為Executor Launcher設(shè)置了特定的JDK版本。
Driver端的JDK版本和spark-submit所在的機(jī)器中的SPARK_HOME環(huán)境變量一致,直接在spark-env.sh中指定即可。
集群缺失特定的JDK版本,且對(duì)集群無(wú)管理權(quán)限
某些特殊的場(chǎng)景下,我們對(duì)集群沒(méi)有管理權(quán)限,只能通過(guò)YARN提交Application,并且集群里沒(méi)有部署我們需要的JDK版本,這種情形就需要將JDK的安裝包也一并提交了。
這里要求我們的JDK安裝包必須為gz格式的,和你代碼打包后的jar包放在同一目錄下,假設(shè)我們下載的JDK的安裝包為:jdk-8u141-linux-x64.tar.gz。
關(guān)鍵配置如下:
$SPARK_HOME/bin/spark-submit \ --conf "spark.yarn.dist.archives=jdk-8u141-linux-x64.tar.gz" \ --conf "spark.executorEnv.JAVA_HOME=./jdk-8u141-linux-x64.tar.gz/jdk1.8.0_141" \ --conf "spark.yarn.appMasterEnv.JAVA_HOME=./jdk-8u141-linux-x64.tar.gz/jdk1.8.0_141" \ ...
我們可以通過(guò)指定spark.yarn.dist.archives
配置,將JDK的安裝包分發(fā)到所有Executor的工作目錄下(包括Application Master的Executor),另外tar.gz的壓縮包也會(huì)被自動(dòng)解壓,假設(shè)jdk-8u141-linux-x64.tar.gz解壓后的目錄為jdk1.8.0_141,那么我們特定的JDK的目錄就是:./jdk-8u141-linux-x64.tar.gz/jdk1.8.0_141,不同的JDK版本以此類推即可。
注意:由于Spark Standalone沒(méi)有提供分發(fā)JDK安裝包并自動(dòng)解壓的功能,所以,這種方式只能用在YARN下。
驗(yàn)證
通過(guò)ps -ef grep查詢相關(guān)進(jìn)程信息,可以看到j(luò)ava的啟動(dòng)路徑為我們特定JDK目錄的java表示配置成功。
如下是我在YARN模式下,單獨(dú)指定JDK版本的Executor的進(jìn)程啟動(dòng)信息:
stan 590751 590745 0 20:45 ? 00:00:14 ./jdk-8u141-linux-x64.tar.gz/jdk1.8.0_141/bin/java -server -Xmx512m -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+G1SummarizeConcMark -XX:InitiatingHeapOccupancyPercent=35 -XX:PermSize=256M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:./gc.log -verbose:gc -Djava.io.tmpdir=/home/stan/tmp/hadoop-stan/nm-local-dir/usercache/stan/appcache/application_1508397483453_0095/container_1508397483453_0095_01_000004/tmp -Dspark.driver.port=52986 -Dspark.yarn.app.container.log.dir=/home/stan//hadoop-2.6.4/logs/userlogs/application_1508397483453_0095/container_1508397483453_0095_01_000004 -XX:OnOutOfMemoryError=kill %p org.apache.spark.executor.CoarseGrainedExecutorBackend --driver-url spark://CoarseGrainedScheduler@10.0.0.110:52986 --executor-id 3 --hostname stan --cores 1 --app-id application_1508397483453_0095 --user-class-path file:/home/stan/tmp/hadoop-stan/nm-local-dir/usercache/stan/appcache/application_1508397483453_0095/container_1508397483453_0095_01_000004/__app__.jar
附:spark application運(yùn)行時(shí)版本不兼容錯(cuò)誤的解決方法
17/06/27 14:34:41 INFO deprecation: mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps 17/06/27 14:34:41 INFO MemoryStore: Block broadcast_0 stored as values in memory (estimated size 788.8 KB, free 1246.5 MB) 17/06/27 14:34:41 INFO MemoryStore: Block broadcast_0_piece0 stored as bytes in memory (estimated size 54.0 KB, free 1246.4 MB) 17/06/27 14:34:41 INFO BlockManagerInfo: Added broadcast_0_piece0 in memory on 10.50.70.121:37335 (size: 54.0 KB, free: 1247.2 MB) 17/06/27 14:34:41 INFO SparkContext: Created broadcast 0 from rdd at TradeInfoOutlier.scala:30 Exception in thread "main" java.lang.NoSuchMethodError: scala.reflect.api.JavaUniverse.runtimeMirror(Ljava/lang/ClassLoader;)Lscala/reflect/api/JavaUniverse$JavaMirror; at com.fangdd.data.profile.outlier.TradeInfoOutlier$.main(TradeInfoOutlier.scala:30) at com.fangdd.data.profile.outlier.TradeInfoOutlier.main(TradeInfoOutlier.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:745) at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:181) at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:206) at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:121) at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala) 17/06/27 14:34:42 INFO SparkContext: Invoking stop() from shutdown hook
這種錯(cuò)誤是由于生產(chǎn)環(huán)境采用的是scala 2.10 + spark1.6.3的運(yùn)行環(huán)境,本地打的application jar使用scala2.11 + spark.1.6.3的編譯環(huán)境,所以放入生產(chǎn)環(huán)境集群報(bào)了上述錯(cuò)誤,更改scala版本重新打jar包后運(yùn)行成功
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
mybatis分割字符串并循環(huán),實(shí)現(xiàn)in多個(gè)參數(shù)的操作
這篇文章主要介紹了mybatis分割字符串并循環(huán),實(shí)現(xiàn)in多個(gè)參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06詳解領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)之事件驅(qū)動(dòng)與CQRS
這篇文章分析了如何應(yīng)用事件來(lái)分離軟件核心復(fù)雜度。探究CQRS為什么廣泛應(yīng)用于DDD項(xiàng)目中,以及如何落地實(shí)現(xiàn)CQRS框架。當(dāng)然我們也要警惕一些失敗的教訓(xùn),利弊分析以后再去抉擇正確的應(yīng)對(duì)之道2021-06-06Eolink上傳文件到Java后臺(tái)進(jìn)行處理的示例代碼
這篇文章主要介紹了Eolink上傳文件到Java后臺(tái)進(jìn)行處理,這里是上傳的excel表格數(shù)據(jù)并轉(zhuǎn)換為java集合對(duì)象、然后進(jìn)行業(yè)務(wù)邏輯處理判斷最后保存到數(shù)據(jù)庫(kù)?,需要的朋友可以參考下2022-12-12Java畢業(yè)設(shè)計(jì)實(shí)戰(zhàn)之教室預(yù)訂管理系統(tǒng)的實(shí)現(xiàn)
這是一個(gè)使用了java+SpringBoot+Maven+Vue+mysql開(kāi)發(fā)的教室預(yù)訂管理系統(tǒng),是一個(gè)畢業(yè)設(shè)計(jì)的實(shí)戰(zhàn)練習(xí),具有教室預(yù)訂管理該有的所有功能,感興趣的朋友快來(lái)看看吧2022-02-02微服務(wù)框架FEIGN使用常見(jiàn)問(wèn)題分析
這篇文章主要為大家介紹了微服務(wù)框架FEIGN常見(jiàn)問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Spring MVC學(xué)習(xí)教程之RequestMappingHandlerMapping匹配
這篇文章主要給大家介紹了關(guān)于Spring MVC學(xué)習(xí)教程之RequestMappingHandlerMapping匹配的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11泛談Java中的不可變數(shù)據(jù)結(jié)構(gòu)
開(kāi)發(fā)人員通常認(rèn)為擁有final引用,或者val在Kotlin或Scala中,足以使對(duì)象不可變。這篇博客文章深入研究了不可變引用和不可變數(shù)據(jù)結(jié)構(gòu),下面小編來(lái)和大家一起學(xué)習(xí)它2019-05-05