Spark独立集群存模型至S3报错:S3AFileSystem无法实例化
解决Spark独立集群保存模型到S3时的ServiceConfigurationError问题
我尝试将训练完成的模型从Spark独立集群保存至S3,但遇到如下错误:
java.util.ServiceConfigurationError: org.apache.hadoop.fs.FileSystem: Provider org.apache.hadoop.fs.s3a.S3AFileSystem could not be instantiated at java.util.ServiceLoader.fail(ServiceLoader.java:232) at java.util.ServiceLoader.access$100(ServiceLoader.java:185) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:384) at java.util.ServiceLoader$LazyIterator.next(ServiceLoader.java:404) at java.util.ServiceLoader$1.next(ServiceLoader.java:480) at org.apache.hadoop.fs.FileSystem.loadFileSystems(FileSystem.java:2631) at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2650) at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2667) at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:94) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2703) at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2685) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:373) at org.apache.spark.util.Utils$.getHadoopFileSystem(Utils.scala:1853) at org.apache.spark.scheduler.EventLoggingListener.<init>(EventLoggingListener.scala:68) at org.apache.spark.SparkContext.<init>(SparkContext.scala:529) at ALS$.main(ALS.scala:32) at ALS.main(ALS.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:775) at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:180) at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:205) at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:119) at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala) Caused by: java.lang.NoClassDefFoundError: com/amazonaws/event/ProgressListener at java.lang.Class.getDeclaredConstructors0(Native Method) at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671) at java.lang.Class.getConstructor0(Class.java:3075) at java.lang.Class.newInstance(Class.java:412) at java.util.ServiceLoader$LazyIterator.nextService(ServiceLoader.java:380) ... 23 more Caused by: java.lang.ClassNotFoundException:com.amazonaws.event.ProgressListener at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 28 more
我已在spark-defaults.conf的extraClassPath中添加hadoop-aws与aws-sdk依赖;尝试过用sbt assembly编译的胖包提交任务,且SBT中已配置相关依赖,主节点环境也已导出AWS凭证。请问该从哪些方向排查解决此问题?
从你的错误栈来看,核心问题是com.amazonaws.event.ProgressListener类找不到,结合你已经做的操作,我建议从以下几个方向排查:
排查依赖版本兼容性
这是最常见的原因:- 确保
hadoop-aws的版本和你集群使用的Hadoop版本完全一致(比如Hadoop 3.3.4对应hadoop-aws-3.3.4),同时搭配的AWS SDK版本要匹配——Hadoop 3.x通常推荐使用aws-sdk-bundle(而不是单独的aws-sdk模块),版本比如1.11.901,避免版本冲突。 - 用
sbt dependencyTree命令查看项目依赖树,检查是否有其他依赖引入了旧版本的AWS SDK,导致和你配置的依赖冲突。如果有,在sbt依赖中添加exclude规则排除冲突的模块。
- 确保
确认Spark集群的类加载配置覆盖所有节点
- 你在
spark-defaults.conf中配置的extraClassPath可能没有被Worker节点正确加载。Spark独立集群中,Worker节点的classpath需要单独配置,或者提交任务时用--jars参数显式指定hadoop-aws和AWS SDK的jar包路径,确保所有Worker节点都能获取到这些依赖。 - 分别检查
spark.driver.extraClassPath和spark.executor.extraClassPath是否都正确配置,有时候只配置了Driver端,Executor端缺失依赖会导致写入S3时失败。
- 你在
检查胖包(Assembly Jar)的构建完整性
- 解压你用sbt assembly生成的胖包,确认里面是否包含
com.amazonaws.event.ProgressListener类。如果没有,说明sbt assembly没有把该依赖打包进去,检查sbt依赖的scope是否设置为compile(而不是provided)。 - 查看sbt assembly的构建日志,是否有重复类或资源的警告。如果有,调整
assemblyMergeStrategy来处理冲突,比如合并重复的配置文件、保留指定版本的类等。
- 解压你用sbt assembly生成的胖包,确认里面是否包含
验证Hadoop S3A配置的正确性
- 确保集群所有节点的
core-site.xml中配置了S3A的实现类:<property> <name>fs.s3a.impl</name> <value>org.apache.hadoop.fs.s3a.S3AFileSystem</value> </property> - 也可以在提交任务时通过
--conf参数直接传递这些配置,比如--conf spark.hadoop.fs.s3a.impl=org.apache.hadoop.fs.s3a.S3AFileSystem,避免节点配置不一致的问题。
- 确保集群所有节点的
确保凭证传递到所有Executor节点
虽然当前错误是类找不到,但如果类加载问题解决后仍有问题,需要确认:- 主节点的AWS凭证环境变量不会自动传递到Worker节点的Executor,提交任务时可以用
--conf spark.executorEnv.AWS_ACCESS_KEY_ID=xxx和--conf spark.executorEnv.AWS_SECRET_ACCESS_KEY=xxx显式传递,或者在Worker节点的spark-env.sh中配置这些变量。
- 主节点的AWS凭证环境变量不会自动传递到Worker节点的Executor,提交任务时可以用
内容的提问来源于stack exchange,提问作者Farah
相关产品推荐
相关产品推荐

