Yarn管理的Spark集群抛出java.lang.ClassNotFoundException问题求助
看起来你遇到的核心问题是Executor进程无法访问到infra.jar中的类——虽然Driver能正常运行,但Executor在YARN容器中的运行环境、权限和路径映射和Standalone模式有不少区别,咱们一步步来排查解决:
1. 优先排查权限问题(最可能的原因)
你把infra.jar放在了/root目录下,但YARN的Executor容器默认是用yarn用户启动的,而/root目录是root用户的私有目录,yarn用户根本没有读取权限!这就导致即使你配置了extraClassPath,Executor也读不到这个jar包。
解决方法:
- 把
infra.jar移动到所有节点的公共可读目录,比如:# 移动到HDP的Spark公共jar目录(yarn用户有权限访问) cp /root/infra.jar /usr/hdp/2.6.3.0-235/spark/jars/ - 同步修改
spark-defaults.conf中的参数(或者直接删除这两个参数,因为放在SPARK_HOME/jars下的jar会自动被Spark加载):spark.executor.extraClassPath=/usr/hdp/2.6.3.0-235/spark/jars/infra.jar spark.driver.extraClassPath=/usr/hdp/2.6.3.0-235/spark/jars/infra.jar
2. 正确使用--jars参数分发依赖
如果不想依赖节点本地的jar包,推荐用HDFS路径来传递--jars参数,这样YARN会自动把jar包分发到所有Executor的容器中,避免本地路径的一致性和权限问题:
步骤:
- 先把
infra.jar上传到HDFS:hdfs dfs -mkdir -p /spark/jars hdfs dfs -put /root/infra.jar /spark/jars/ - 提交任务时指定
--jars参数:$SPARK_HOME/bin/spark-submit --master yarn --class com.MyMainClass --jars hdfs:///spark/jars/infra.jar /root/program.jar
注意:
--jars后面如果有多个jar要用逗号分隔,HDFS路径要写全(如果集群有HA可以用名称节点的逻辑名称)。
3. 检查Spark参数的优先级
Spark的参数优先级是:命令行参数 > spark-defaults.conf > Spark代码中的配置,如果你之前用--jars没生效,可能是因为spark-defaults.conf中的extraClassPath参数和--jars冲突了?可以暂时注释掉spark.executor.extraClassPath和spark.driver.extraClassPath,只保留--jars参数试试。
4. 备选方案:打包依赖到主Jar
如果上述方法都不行,可以考虑把infra.jar的内容打包到program.jar中,用Maven的shade插件或者Gradle的shadow插件,这样就不用额外传递依赖Jar了。不过这种方法要注意类冲突问题(比如不同Jar中存在同名类),需要在打包时处理冲突。
内容的提问来源于stack exchange,提问作者antonpuz

