YARN集群模式spark-submit报java.lang.NoClassDefFoundError求助
解决YARN Cluster模式下Spark提交的NoClassDefFoundError问题
从你的描述和错误日志来看,问题的核心在于YARN Cluster模式与Client/Standalone模式的运行机制差异:
- Client模式下,Driver运行在你提交命令的本地机器上,能直接访问本地的
emr-core-1.0-SNAPSHOT.jar; - Standalone模式下,Spark会自动把本地jar分发到所有Worker节点;
- 但YARN Cluster模式下,Driver是运行在YARN集群的某个NodeManager节点上的,这个节点无法访问你本地机器上的
/home/hadoop/emr/deployment/server/emr-core-1.0-SNAPSHOT.jar路径,导致类加载失败。
下面是几种可行的解决方法:
方法1:将依赖jar上传到HDFS,使用HDFS路径引用
这是最常用的解决方案,因为集群所有节点都能访问HDFS:
- 先把
emr-core-1.0-SNAPSHOT.jar上传到HDFS的某个路径:
hdfs dfs -mkdir -p /user/hadoop/spark-jars/ hdfs dfs -put /home/hadoop/emr/deployment/server/emr-core-1.0-SNAPSHOT.jar /user/hadoop/spark-jars/
- 修改spark-submit命令,把
--jars参数换成HDFS路径:
spark-submit \ --class com.example.hdfs.spark.RawDataAdapter \ --master yarn \ --deploy-mode cluster \ --jars hdfs://111.11.11.111:8020/user/hadoop/spark-jars/emr-core-1.0-SNAPSHOT.jar \ /home/hadoop/emr-spark-1.0-SNAPSHOT.jar \ hdfs://111.11.11.111:8020/user/hdfsinputfile.zip 8000
方法2:使用--archives参数分发jar到集群节点
可以通过--archives将jar归档到YARN容器的本地目录,然后在--jars里引用本地路径:
spark-submit \ --class com.example.hdfs.spark.RawDataAdapter \ --master yarn \ --deploy-mode cluster \ --archives hdfs://111.11.11.111:8020/user/hadoop/spark-jars/emr-core-1.0-SNAPSHOT.jar#emr-core.jar \ --jars ./emr-core.jar \ /home/hadoop/emr-spark-1.0-SNAPSHOT.jar \ hdfs://111.11.11.111:8020/user/hdfsinputfile.zip 8000
这里的#emr-core.jar是给归档的jar起一个别名,方便在容器里用相对路径引用。
方法3:将依赖jar放到集群所有节点的Spark classpath(不推荐,灵活性差)
如果这个jar是所有Spark任务都需要的通用依赖,可以把它复制到每个集群节点的$SPARK_HOME/jars目录下,然后重启Spark服务。但这种方法维护成本高,不适合仅个别任务需要的依赖。
另外还要注意:你的原始命令里home/hadoop/emr-spark-1.0-SNAPSHOT.jar少了开头的/,虽然可能是笔误,但也要确保这个jar的路径在提交节点是正确的,或者同样上传到HDFS引用。
内容的提问来源于stack exchange,提问作者Satya
相关产品推荐
相关产品推荐

