Apache Spark:类加载器在 jar 中找不到 classDef

tri*_*oid 5 java scala classloader apache-spark

我正在 Apache Spark 中以本地模式运行一个作业,该作业会将其结果保存到 s3a 文件系统。由于 Hadoop 2.6 没有 s3a:// 实现(或 s3://、s3n://)。我打包了一个 uber jar,其中包含 hadoop-aws 2.6.0 的所有传递依赖项,并将其与我的主要工作的 jar 一起提交。

但是,当我使用以下简约代码对其进行测试时:

sc.parallelize(1 to 100).saveAsTextFile("s3a://***/test10/")
Run Code Online (Sandbox Code Playgroud)

编译器在第一次运行时给了我这个错误:

java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory
    at com.amazonaws.auth.AWSCredentialsProviderChain.<clinit>(AWSCredentialsProviderChain.java:41)
    at org.apache.hadoop.fs.s3a.S3AFileSystem.initialize(S3AFileSystem.java:112)
    at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2596)
    at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:91)
    at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2630)
    at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2612)
    at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:370)
    at org.apache.hadoop.fs.Path.getFileSystem(Path.java:296)
    at org.apache.spark.SparkHadoopWriter$.createPathFromString(SparkHadoopWriter.scala:170)
    at org.apache.spark.rdd.PairRDDFunctions.saveAsHadoopFile(PairRDDFunctions.scala:953)
    at org.apache.spark.rdd.PairRDDFunctions.saveAsHadoopFile(PairRDDFunctions.scala:863)
    at org.apache.spark.rdd.RDD.saveAsTextFile(RDD.scala:1290)
Run Code Online (Sandbox Code Playgroud)

如果我尝试再次运行,则会出现以下错误:

java.lang.NoClassDefFoundError: Could not initialize class com.amazonaws.auth.AWSCredentialsProviderChain
    at org.apache.hadoop.fs.s3a.S3AFileSystem.initialize(S3AFileSystem.java:112)
    at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2596)
    at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:91)
    at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2630)
    at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2612)
    at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:370)
    at org.apache.hadoop.fs.Path.getFileSystem(Path.java:296)
    at org.apache.spark.SparkHadoopWriter$.createPathFromString(SparkHadoopWriter.scala:170)
    at org.apache.spark.rdd.PairRDDFunctions.saveAsHadoopFile(PairRDDFunctions.scala:953)
    at org.apache.spark.rdd.PairRDDFunctions.saveAsHadoopFile(PairRDDFunctions.scala:863)
    at org.apache.spark.rdd.RDD.saveAsTextFile(RDD.scala:1290)
Run Code Online (Sandbox Code Playgroud)

奇怪的是:LogFactory 和 AWSCredentialsProviderChain 都在我提到的 uber jar 中。我还检查了其他 jar,包括工人上的 Spark 库和我的主要工作的 jar(已部署到 Spark/worker 目录),并且可以确认它们都没有具有相同名称的类。所以它不可能是一个 jar hell 问题(此外,在这种情况下抛出的错误应该是 Property/MethodNotFoundError)。您知道可能发生了什么以及如何解决它吗?

小智 2

我之前遇到过类似的问题,我的解决方案是在运行 Spark-submit 时将 uber jar 本身添加到 --driver-class-path 中。您的 uber-jar 不是直接由 JVM 执行的。相反,它由 Spark 的某种驱动程序包装器运行。将 uber jar 添加到驱动程序的类路径似乎没有必要,但有时可以解决一些奇怪的 NoClassDefFoundError。我不确定它是否可以解决您的问题,但值得一试。