• 提交Spark作业遇到的NoSuchMethodError问题


    问题:
    提交spark任务,hive写ck,部分executor报错
    java.lang.NoSuchMethodError: org.apache.http.impl.conn.PoolingHttpClientConnectionManager.setValidateAfterInactivity
    其他不报错的executor均能写入ck
    判断为httpclient包冲突,但maven tree显示本地并无冲突
    尝试:
    jar包打fatjar,无用;
    使用–jar提交依赖包;无用;
    并报错:
    ERROR TransportRequestHandler: Error while invoking RpcHandler#receive() for one-way message.
    org.apache.spark.SparkException: Could not find CoarseGrainedScheduler.
    后参考以下文章,得到解决:
    源:https://www.cnblogs.com/ljhbjehp/p/15230217.html
    提交Spark作业遇到的NoSuchMethodError问题总结
    测试应用说明
    测试的Spark应用实现了同步hive表到kafka的功能。具体处理流程:

    ETCD 获取 SQL 语句和 Kafka 配置信息
    使用 SparkSQL 读取 Hive 数据表
    把 Hive 数据表的数据写入 Kafka
    应用使用etcd来存储程序所需配置,通过拉取etcd的kv配置,来初始化sql语句和kafka配置的参数。

    提交方式及相应的问题
    使用client模式,提交无依赖的jar包
    提交命令

    /usr/local/spark-2.3.0-bin-2.8.2/bin/spark-submit
    –name hive2kafka
    –master yarn
    –deploy-mode client
    –driver-cores 1
    –driver-memory 2g
    –num-executors 2
    –executor-cores 1
    –executor-memory 2g
    –queue hive
    –class com.ljh.spark.Hive2Kafka
    /data0/jianhong1/demo-v25/target/demo-1.0-SNAPSHOT.jar
    应用运行失败,driver端报错:

    Exception in thread “main” java.lang.NoClassDefFoundError: io/etcd/jetcd/Client
    at com.ljh.spark.EtcdUtil.getClient(EtcdUtil.java:27)
    at com.ljh.spark.EtcdUtil.get(EtcdUtil.java:46)
    at com.ljh.spark.Hive2Kafka.main(Hive2Kafka.java:60)

    Caused by: java.lang.ClassNotFoundException: io.etcd.jetcd.Client
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    从报错信息可以看出,driver端没有查找到etcd的某个类,即没有加载到etcd 的jar包。说明spark应用driver进程的classpath不包含etcd 的jar包。因此考虑打包fat jar,把etcd的jar包打入用户提交的jar。

    使用client模式,提交包含依赖的jar包
    提交命令

    /usr/local/spark-2.3.0-bin-2.8.2/bin/spark-submit
    –name hive2kafka
    –master yarn
    –deploy-mode client
    –driver-cores 1
    –driver-memory 2g
    –num-executors 2
    –executor-cores 1
    –executor-memory 2g
    –queue hive
    –class com.ljh.spark.Hive2Kafka
    /data0/jianhong1/demo-v25/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar

    应用运行失败,driver端报错:

    Exception in thread “main” java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;CLjava/lang/Object;)V
    at io.grpc.Metadata K e y . v a l i d a t e N a m e ( M e t a d a t a . j a v a : 742 ) a t i o . g r p c . M e t a d a t a Key.validateName(Metadata.java:742) at io.grpc.Metadata Key.validateName(Metadata.java:742)atio.grpc.MetadataKey.(Metadata.java:750)
    at io.grpc.Metadata K e y . < i n i t > ( M e t a d a t a . j a v a : 668 ) a t i o . g r p c . M e t a d a t a Key.(Metadata.java:668) at io.grpc.Metadata Key.<init>(Metadata.java:668)atio.grpc.MetadataAsciiKey.(Metadata.java:959)
    at io.grpc.Metadata A s c i i K e y . < i n i t > ( M e t a d a t a . j a v a : 954 ) a t i o . g r p c . M e t a d a t a AsciiKey.(Metadata.java:954) at io.grpc.Metadata AsciiKey.<init>(Metadata.java:954)atio.grpc.MetadataKey.of(Metadata.java:705)
    at io.grpc.Metadata$Key.of(Metadata.java:701)
    at io.etcd.jetcd.ClientConnectionManager.(ClientConnectionManager.java:69)
    at io.etcd.jetcd.ClientImpl.(ClientImpl.java:37)
    at io.etcd.jetcd.ClientBuilder.build(ClientBuilder.java:401)
    at com.ljh.spark.EtcdUtil.getClient(EtcdUtil.java:28)
    at com.ljh.spark.EtcdUtil.get(EtcdUtil.java:46)
    at com.ljh.spark.Hive2Kafka.main(Hive2Kafka.java:60)

    从报错信息可以看出,应用没有找到guava包的Preconditions类的checkArgument方法 。说明程序找到了guava包的Preconditions类,但是这个类没有找到checkArgument的某个构造方法。这种问题一般是由于jar包冲突,即程序加载了低版本的jar包,但是程序需要调用高版本jar包的某个方法,而这个方法低版本中没有,就会出现上面的报错NoSuchMethodError。

    因此考虑把程序中冲突的低版本guava包排除掉。通过检查程序pom文件的jar包依赖,明确添加适配etcd高版本的guava包,并把冲突的低版本的guava包排除掉。重新运行,发现依然出现上面的NoSuchMethodError报错。

    因此猜测低版本的guava包不是由于程序代码引入的,而是由spark提交机的本地包引入的。通过检查spark提交机的本地包,查到引入了guava-14.0.1.jar,而程序中etcd依赖的guava包需要的版本为20+。说明应用使用了本地jar的低版本guava类,而没有使用fat-jar的高版本guava类。由此推测出,spark应用driver端的类加载优先级:本地jar > fat-jar。

    使用client模式,提交包含依赖的jar包,并添加driver-class 类路径
    提交命令

    /usr/local/spark-2.3.0-bin-2.8.2/bin/spark-submit
    –name hive2kafka
    –master yarn
    –deploy-mode client
    –driver-class-path /data0/jianhong1/demo-v25/target/lib/guava-23.6-jre.jar:/data0/jianhong1/demo-v25/target/lib/protobuf-java-3.5.1.jar
    –driver-cores 1
    –driver-memory 2g
    –num-executors 2
    –executor-cores 1
    –executor-memory 2g
    –queue hive
    –class com.ljh.spark.Hive2Kafka
    /data0/jianhong1/demo-v25/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar
    程序正常运行,不再出现NoSuchMethodError报错。由此推测出,spark应用driver端的类加载优先级:driver-class-path 配置 > 本地jar。

    使用cluster模式,提交包含依赖的jar包
    提交命令

    /usr/local/spark-2.3.0-bin-2.8.2/bin/spark-submit
    –name hive2kafka
    –master yarn
    –deploy-mode cluster
    –driver-cores 1
    –driver-memory 2g
    –num-executors 2
    –executor-cores 1
    –executor-memory 2g
    –queue hive
    –class com.ljh.spark.Hive2Kafka
    /data0/jianhong1/demo-v25/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar
    应用运行失败,报错信息:

     diagnostics: User class threw exception: java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;CLjava/lang/Object;)V
    at io.grpc.Metadata$Key.validateName(Metadata.java:742)
    at io.grpc.Metadata$Key.(Metadata.java:750)
    at io.grpc.Metadata$Key.(Metadata.java:668)
    at io.grpc.Metadata$AsciiKey.(Metadata.java:959)
    at io.grpc.Metadata$AsciiKey.(Metadata.java:954)
    at io.grpc.Metadata$Key.of(Metadata.java:705)
    at io.grpc.Metadata$Key.of(Metadata.java:701)
    at io.etcd.jetcd.ClientConnectionManager.(ClientConnectionManager.java:69)
    at io.etcd.jetcd.ClientImpl.(ClientImpl.java:37)
    at io.etcd.jetcd.ClientBuilder.build(ClientBuilder.java:401)
    at com.ljh.spark.EtcdUtil.getClient(EtcdUtil.java:28)
    at com.ljh.spark.EtcdUtil.get(EtcdUtil.java:46)
    at com.ljh.spark.Hive2Kafka.main(Hive2Kafka.java:66)
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    从报错信息可以看出,应用找到了guava包的Preconditions类,但是在这个类中没有找到checkArgument的某个构造方法。

    因此考虑在提交作业时明确指出etcd所依赖的高版本guava包。于是提交参数添加了 --jars hdfs:/user/jianhong1/jars/guava-23.6-jre.jar,hdfs:/user/jianhong1/jars/protobuf-java-3.5.1.jar \,重新运行后依然报上面的错。说明 --jar 参数只是负责把jar包拷贝到运行作业的服务器上,但是没把指定的jar包加到类路径。

    使用cluster模式,提交包含依赖的jar包,并添加driver 和executor 类路径。
    提交命令

    /usr/local/spark-2.3.0-bin-2.8.2/bin/spark-submit
    –name hive2kafka
    –master yarn
    –deploy-mode cluster
    –driver-cores 1
    –driver-memory 2g
    –num-executors 2
    –executor-cores 1
    –executor-memory 2g
    –queue hive
    –class com.ljh.spark.Hive2Kafka
    –conf spark.driver.extraClassPath=guava-23.6-jre.jar:protobuf-java-3.5.1.jar
    –conf spark.executor.extraClassPath=guava-23.6-jre.jar:protobuf-java-3.5.1.jar
    –jars hdfs:/user/jianhong1/jars/guava-23.6-jre.jar,hdfs:/user/jianhong1/jars/protobuf-java-3.5.1.jar
    /data0/jianhong1/demo-v25/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar
    通过增加guava包的driver 和executor 类路径的配置后,应用成功运行!

    总结
    本文介绍了client 方式和cluster 方式提交Spark 应用时所遇到的NoSuchMethodError 问题,及相应的解决方案。通过实际测试得到结论: spark应用的类加载优先级:–driver-class-path 或–executor-class-path配置 > 本地jar > fat-jar。

    参考
    https://stackoverflow.com/questions/37132559/add-jars-to-a-spark-job-spark-submit
    The --jars argument only transports the jars to each machine in the cluster. It does NOT tell spark to use them in the class path search. The --driver-class-path (or similar arguments or config parameters) are also required.
    –jars 参数只是用于传输 jar 包到集群的 Executor 和 Driver 的服务器上,它不会告知 spark 应用在哪个类路径下使用这些jar包。因此,–driver-class-path或–executor-class-path参数也是必需的,用于配置 driver 和 executor 的类路径。
    Spark on Yarn运行时加载的jar包 https://www.cnblogs.com/upupfeng/p/13544612.html
    spark on yarn运行时会加载的jar包有如下:
    spark-submit中指定的–jars
    $SPARK_HOME/jars下的jar包
    yarn提供的jar包
    spark-submit通过参数spark.driver/executor.extraClassPath指定的jar包
    http://spark.apache.org/docs/latest/running-on-yarn.html 官网文档

  • 相关阅读:
    Android实现两台手机屏幕共享和远程控制
    java工程师进阶之路—java学习路线
    VSCode设置中文语言界面(VScode设置其他语言界面)
    Mysql数据库架构介绍
    CloudStack 4.17 安装部署
    Java 入门练习(26 - 30)
    线阵相机之行触发
    【freeRTOS】操作系统之三-信号量
    北京大学肖臻老师《区块链技术与应用》公开课笔记:比特币原理(三):分叉、匿名性
    [ vulhub漏洞复现篇 ] zabbix SQL注入漏洞 (CVE-2016-10134)
  • 原文地址:https://blog.csdn.net/daxiongwuwuwuw/article/details/126780082