大家在使用Spark、MapReduce 或 Flink 的时候很可能遇到这样一种情况:Hadoop 集群使用的 JDK 版本为1.7.x,而我们自己编写的程序由于某些原因必须使用 1.7 以上版本的JDK,这时候如果我们直接使用 JDK 1.8、或 1.9 来编译我们写好的代码,然后直接提交到 YARN 上运行,这时候会遇到以下的异常:
Exception in thread "main" java.lang.UnsupportedClassVersionError: com/iteblog/mobile/UserMobileInfo : Unsupported major.minor version 52.0 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:800) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:449) at java.net.URLClassLoader.access$100(URLClassLoader.java:71) at java.net.URLClassLoader$1.run(URLClassLoader.java:361) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:354) at java.lang.ClassLoader.loadClass(ClassLoader.java:425) at java.lang.ClassLoader.loadClass(ClassLoader.java:358) at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2531) at java.lang.Class.getMethod0(Class.java:2774) at java.lang.Class.getMethod(Class.java:1663) at org.apache.spark.deploy.yarn.ApplicationMaster.startUserApplication(ApplicationMaster.scala:537) at org.apache.spark.deploy.yarn.ApplicationMaster.runDriver(ApplicationMaster.scala:319) at org.apache.spark.deploy.yarn.ApplicationMaster.run(ApplicationMaster.scala:185) at org.apache.spark.deploy.yarn.ApplicationMaster$$anonfun$main$1.apply$mcV$sp(ApplicationMaster.scala:653) at org.apache.spark.deploy.SparkHadoopUtil$$anon$1.run(SparkHadoopUtil.scala:69) at org.apache.spark.deploy.SparkHadoopUtil$$anon$1.run(SparkHadoopUtil.scala:68) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:415) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1491) at org.apache.spark.deploy.SparkHadoopUtil.runAsSparkUser(SparkHadoopUtil.scala:68) at org.apache.spark.deploy.yarn.ApplicationMaster$.main(ApplicationMaster.scala:651) at org.apache.spark.deploy.yarn.ApplicationMaster.main(ApplicationMaster.scala)
原因很简单,YARN 集群的 JDK 版本低于我们客户端需要的 JDK 版本.Java 8 class file的版本是52,而 Java 7虚拟机只能支持到51,所以肯定会出现上述异常。那我们该如何解决呢?
首先想到的是升级 YARN 集群上面的 JDK 版本到1.8,但是如果很多人都在使用 YARN 集群,这种操作势必影响很多用户,所以这种方法不适合。那有没有更好的办法?肯定有,要不然就没有这篇文章了。
其实我们可以在提交作业之前设置好相关的环境变量,然后再提交,这时候在YARN上执行这个作业的时候就会使用到我们指定的 JDK ,但是前提是我们必须在 YARN 集群的每台节点安装好相应 JDK 版本。下面我将介绍 Spark 、MapReduce 以及 Flink 中如何指定 JAVA_HOME。
Spark
Spark 中有两种方式:
通过指定SPARK_YARN_USER_ENV
这个很简单,直接通过 SPARK_YARN_USER_ENV
环境变量设置好 YARN 集群 JDK 的路径即可,如下:
export SPARK_YARN_USER_ENV="JAVA_HOME=/home/iteblog/java/jdk1.8.0_25"
设置好之后,然后就可以正常提交 Spark 作业,这时候 Spark 在 YARN 上将会使用 jdk1.8.0_25 运行。但是请记住,SPARK_YARN_USER_ENV
环境变量是很早之前的环境变量,并且早就被遗弃了,所以不推荐使用。
通过参数设置
推荐使用的是 spark.executorEnv.JAVA_HOME
和 spark.yarn.appMasterEnv.JAVA_HOME
,这分别为 Spark 的 Executor 和 Driver 指定 JDK 路径,如下:
$SPARK_HOME/bin/spark-submit --master yarn-cluster \ --executor-memory 8g \ --num-executors 80 \ --queue iteblog \ --conf "spark.yarn.appMasterEnv.JAVA_HOME=/home/iteblog/java/jdk1.8.0_25" \ --conf "spark.executorEnv.JAVA_HOME=/home/iteblog/java/jdk1.8.0_25" \ --executor-cores 1 \ --class com.iteblog.UserActionParser /home/iteblog/spark/IteblogAction-1.0-SNAPSHOT.jar
当然,你也可以将这个参数写到 $SPARK_HOME/conf/spark_default.conf
文件中。其他的环境变量也可以通过这些设置,比如 spark.executorEnv.MY_BLOG=www.iteblog.com
这样我们就可以从程序里面获取 MY_BLOG
环境变量的值。
MapReduce
我们可以通过 MapReduce 程序里面的 Configuration
设置,如下:
conf.set("mapred.child.env", "JAVA_HOME=/home/iteblog/java/jdk1.8.0_25"); conf.set("yarn.app.mapreduce.am.env", "JAVA_HOME=/home/iteblog/java/jdk1.8.0_25");
Flink
Flink 也是支持自定义 JAVA_HOME
,我们可以在 $FLINK_HOME/conf/flink-conf.yaml
,如下:
env.java.home: /home/iteblog/java/jdk1.8.0_25
注意,上面所说的 JDK 路径全部都是指 YARN 集群的 JDK 路径。
本博客文章除特别声明,全部都是原创!原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
本文链接: 【如何在Spark、MapReduce和Flink程序里面指定JAVA_HOME】(https://www.iteblog.com/archives/1883.html)
哈喽,老板,咨询一个问题,flink只能通过修改配置文件吗?能不能通过-D指定