Spark集成S3时采用--jars导入依赖报错的原因及解决
原因分析
命令格式错误是触发当前NoClassDefFoundError的直接原因
Spark的--jars参数对输入格式有严格要求:多jar路径必须使用无空格的英文逗号拼接。原启动命令中两个路径之间写为, (逗号加前后空格),Spark解析参数时会在第一个空格位置截断--jars的输入值,最终只会加载/tmp/hadoop-aws-3.2.0.jar,后续带空格的路径、逗号内容都会被识别为shell独立参数,完全不会进入类加载路径。
而报错缺失的com.amazonaws.AmazonServiceException类正是存放在aws-java-sdk的jar包中,该包未被加载时自然会抛出类定义找不到的异常。
手动指定本地jar缺少依赖解析逻辑是深层隐患
--packages参数能正常运行,是因为它会自动解析指定包的完整Maven依赖树,把所有关联的传递依赖全部拉取加载。而--jars参数是纯路径透传,不会做任何依赖解析:
- 仅导入hadoop-aws和aws-java-sdk两个包时,往往会缺失二者关联的运行依赖(如aws-java-sdk-core、jackson序列化组件、http客户端组件、hadoop-auth适配组件等)
- 依赖版本不匹配时也会触发类找不到、方法签名异常等问题
基于
--jars参数的正确实现步骤 - 修正启动命令的格式问题
移除所有路径拼接处的空格,所有路径拼接处绝对不能出现空格,基础格式为:spark-shell --jars /tmp/hadoop-aws-3.2.0.jar,/tmp/aws-java-sdk-1.11.967.jar - 补全所有关联依赖jar
将与现有两个包版本匹配的全部运行依赖jar,统一存放到本地固定目录后,将所有jar路径用无空格逗号拼接,依次追加到--jars参数末尾。需要补充的核心依赖包括:- 与aws-java-sdk同版本的aws-java-sdk-core
- 兼容版本的httpclient、httpcore组件
- 匹配hadoop-aws 3.2.0版本的jackson序列化三件套(jackson-core、jackson-databind、jackson-annotations)
- 匹配hadoop-aws 3.2.0版本的hadoop-auth组件
- 完成S3A配置与功能验证
进入spark-shell后,执行以下配置完成类映射:
执行读取逻辑验证连通性:sc.hadoopConfiguration.set("fs.s3.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem") sc.hadoopConfiguration.set("fs.s3a.aws.credentials.provider", "com.amazonaws.auth.DefaultAWSCredentialsProviderChain")sc.textFile("s3://test/testdata.txt").foreach(println)
注意:如果出现权限类报错,可补充设置AK/SK相关的配置项,逻辑与
--packages模式下的配置完全一致。
内容的提问来源于stack exchange,提问作者Machi
相关产品推荐
相关产品推荐

