Scala Spark submit任务写入GCS本地正常集群报gs协议错误如何解决
问题根因
本地IntelliJ运行正常是因为运行时会加载你sbt配置里的所有依赖,包括gcs-connector,而提交到集群失败是由以下几个常见原因叠加导致的:
- 依赖版本不匹配:你sbt里引入的是
gcs-connector%hadoop3-2.0.0,适配的是Hadoop3.x版本,但你项目依赖的Hadoop是2.7.3,集群如果也是Hadoop2.x版本的话,该版本连接器无法正常被加载识别。 - 集群类加载优先级问题:Spark on YARN默认会优先加载集群自身的Hadoop依赖包,如果集群节点上没有预装gcs-connector,即便你把连接器打进作业Jar,也可能被YARN的类加载机制屏蔽,导致无法找到gs协议的实现类。
- 提交命令配置错误:你描述中说把master改成了yarn,但实际提交命令里仍然写的是
--master local,同时你代码里的主类是DFToGCSLite,但提交命令指定的class是com.test.migration.CSVToGCS,二者不匹配也会导致配置不生效。 - 配置生效范围问题:你在代码里给SparkContext的hadoopConfiguration设置参数,仅对Driver端生效,YARN模式下Executor端无法拿到该配置,也会导致Executor读写GCS时找不到实现类。
排查解决步骤
1. 修正依赖版本
把sbt里的gcs-connector依赖替换为适配Hadoop2.x的版本:
"com.google.cloud.bigdataoss" % "gcs-connector" % "hadoop2-2.0.0"
如果用assembly打包,确认打包配置没有把gcs-connector相关类排除到Jar外。
2. 修正提交命令与参数
首先确保提交命令的master配置、主类和实际代码一致,同时额外添加配置把gcs连接器依赖传到所有Executor节点,并且指定类加载优先使用作业Jar的依赖:
/usr/local/bin/spark-submit \ --class com.test.migration.DFToGCSLite \ --master yarn \ --deploy-mode cluster \ --conf spark.driver.extraClassPath=CSVToGCS-assembly-0.0.1.jar \ --conf spark.executor.extraClassPath=CSVToGCS-assembly-0.0.1.jar \ --conf spark.hadoop.fs.gs.impl=com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem \ --conf spark.hadoop.fs.AbstractFileSystem.gs.impl=com.google.cloud.hadoop.fs.gcs.GoogleHadoopFS \ --conf spark.hadoop.google.cloud.auth.service.account.enable=true \ --conf spark.hadoop.google.cloud.auth.service.account.json.keyfile=<集群上的密钥共享路径> \ /Users/adam.mac/Desktop/csv_to_gcs/target/scala-2.11/CSVToGCS-assembly-0.0.1.jar
- 把所有Hadoop/GCS相关配置放到spark-submit参数里,能保证Driver和Executor都能拿到统一配置,避免代码里设置仅Driver生效的问题。
3. 可选:集群预装gcs-connector
如果作业较多,也可以直接把对应Hadoop版本的gcs-connector Jar包放到集群所有节点的$SPARK_HOME/jars和$HADOOP_HOME/share/hadoop/common/lib目录下,重启Spark和Hadoop服务后,所有作业都可以直接识别gs协议,不需要每个作业单独打依赖。
内容的提问来源于stack exchange,提问作者it243
相关产品推荐
相关产品推荐

