如何为Spark Application指定不同的JDK版本详解

 更新时间:2017年11月29日 09:43:40   作者:StanZhai  
这篇文章主要给大家介绍了关于如何为Spark Application指定不同的JDK版本的相关资料,文中通过示例代码将解决的方法介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友下面来随着小编一起学习学习吧。

前言

随着企业内部业务系统越来越多,基于JVM的服务,通常情况线上环境可能会有多套JDK跑不同的服务。大家都知道基于高版本的Java规范编写的服务跑在低版本的JVM上会出现:java.lang.UnsupportedClassVersionError的异常。

Spark 2.2开始移除了对Java 7的支持,大多数情况下,我们的Spark Application是和Hadoop系统公用的JDK,如果Hadoop依赖的JDK版本是7,那我们基于JDK 8编写的Application跑在上面就会出问题。

该文主要介绍在不同的场景下,如何为Spark Application指定不同的JDK版本。

集群已部署了指定的JDK版本

假设集群中每个节点JDK的部署路径为:/usr/java/jdk1.8

Spark提供了spark.executorEnv.[EnvironmentVariableName]配置,可以用来给Executor进程添加环境变量,如果Spark Application使用的集群管理器是Standalone,只需要通过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环境变量,如下:

$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上的时候,spark.yarn.appMasterEnv.JAVA_HOME相当于为Spark Application的Driver设置了特定的JDK版本;

以client的模式部署时,spark.yarn.appMasterEnv.JAVA_HOME仅仅是为Executor Launcher设置了特定的JDK版本。

Driver端的JDK版本和spark-submit所在的机器中的SPARK_HOME环境变量一致,直接在spark-env.sh中指定即可。

集群缺失特定的JDK版本,且对集群无管理权限

某些特殊的场景下,我们对集群没有管理权限,只能通过YARN提交Application,并且集群里没有部署我们需要的JDK版本,这种情形就需要将JDK的安装包也一并提交了。

这里要求我们的JDK安装包必须为gz格式的,和你代码打包后的jar包放在同一目录下,假设我们下载的JDK的安装包为:jdk-8u141-linux-x64.tar.gz。

关键配置如下:

$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" \
 ...

我们可以通过指定spark.yarn.dist.archives配置,将JDK的安装包分发到所有Executor的工作目录下(包括Application Master的Executor),另外tar.gz的压缩包也会被自动解压,假设jdk-8u141-linux-x64.tar.gz解压后的目录为jdk1.8.0_141,那么我们特定的JDK的目录就是:./jdk-8u141-linux-x64.tar.gz/jdk1.8.0_141,不同的JDK版本以此类推即可。

注意:由于Spark Standalone没有提供分发JDK安装包并自动解压的功能,所以,这种方式只能用在YARN下。

验证

通过ps -ef grep查询相关进程信息,可以看到java的启动路径为我们特定JDK目录的java表示配置成功。

如下是我在YARN模式下,单独指定JDK版本的Executor的进程启动信息:

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运行时版本不兼容错误的解决方法

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 

这种错误是由于生产环境采用的是scala 2.10 + spark1.6.3的运行环境,本地打的application jar使用scala2.11 + spark.1.6.3的编译环境,所以放入生产环境集群报了上述错误,更改scala版本重新打jar包后运行成功

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

  • Spring Boot项目传参校验的最佳实践指南

    Spring Boot项目传参校验的最佳实践指南

    有参数传递的地方都少不了参数校验,在web开发中前端的参数校验是为了用户体验,后端的参数校验是为了安全,下面这篇文章主要给大家介绍了关于Spring Boot项目传参校验的最佳实践,需要的朋友可以参考下
    2022-04-04
  • Java简单实现UDP和TCP的示例

    Java简单实现UDP和TCP的示例

    下面小编就为大家带来一篇Java简单实现UDP和TCP的示例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • java Jersey框架初体验

    java Jersey框架初体验

    本篇主要是Jersey体验,你将在不做任何编码的情况下,体验Jersey框架的神气魅力!本文还假定你在eclipse里安装了Maven插件
    2016-07-07
  • Java中get/post的https请求忽略ssl证书认证浅析

    Java中get/post的https请求忽略ssl证书认证浅析

    因为Java在安装的时候,会默认导入某些根证书,所以有些网站不导入证书,也可以使用Java进行访问,这篇文章主要给大家介绍了关于Java中get/post的https请求忽略ssl证书认证的相关资料,需要的朋友可以参考下
    2024-01-01
  • Java基础之练习打印三角形

    Java基础之练习打印三角形

    这篇文章主要介绍了Java基础之练习打印三角形,文中有非常详细的代码示例,对正在学习java基础的小伙伴们有非常好的帮助,需要的朋友可以参考下
    2021-04-04
  • Java 手写LRU缓存淘汰算法

    Java 手写LRU缓存淘汰算法

    本文主要讲了如何通过哈希链表这种数据结构来实现LRU算法,提供了三种实现思路,第一种从双向链表开始,借助于HashMap来实现满足要求的LRUCache
    2021-05-05
  • Mybatis批量更新报错问题

    Mybatis批量更新报错问题

    这篇文章主要介绍了Mybatis批量更新报错的问题及解决办法,包括mybatis批量更新的两种方式,需要的的朋友参考下
    2017-01-01
  • spring @Conditional的使用与扩展源码分析

    spring @Conditional的使用与扩展源码分析

    这篇文章主要介绍了spring @Conditional的使用与扩展,这里需要注意如果Condition返回的是false,那么spirng就不会对方法或类进行解析,具体源码分析跟随小编一起看看吧
    2022-03-03
  • springboot下使用shiro自定义filter的个人经验分享

    springboot下使用shiro自定义filter的个人经验分享

    这篇文章主要介绍了springboot下使用shiro自定义filter的个人经验,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java基于socket实现简易聊天室实例

    Java基于socket实现简易聊天室实例

    这篇文章主要介绍了Java基于socket实现简易聊天室的方法,实例分析了java基于socket实现聊天室服务端与客户端的相关技巧,需要的朋友可以参考下
    2015-05-05

最新评论