如何使用用户提供的 Hadoop 正确配置 Spark 2.4

Posted

技术标签:

【中文标题】如何使用用户提供的 Hadoop 正确配置 Spark 2.4【英文标题】:How to configure Spark 2.4 correctly with user-provided Hadoop 【发布时间】:2020-06-14 12:05:42 【问题描述】:

我想使用 Spark 2.4.5(当前稳定的 Spark 版本)和 Hadoop 2.10(当前稳定的 Hadoop 2.x 系列版本)。此外,我还需要访问 HDFS、Hive、S3 和 Kafka。

http://spark.apache.org 提供预先构建的 Spark 2.4.5,并与 Hadoop 2.6 或 Hadoop 2.7 捆绑在一起。 另一种选择是将 Spark 与用户提供的 Hadoop 一起使用,所以我尝试了那个。

由于与用户提供的 Hadoop 一起使用,Spark 也不包含 Hive 库。 会有错误,像这里:How to create SparkSession with Hive support (fails with "Hive classes are not found")?

当我将 spark-hive 依赖项添加到 spark-shell 时(spark-submit 也会受到影响)使用

spark.jars.packages=org.apache.spark:spark-hive_2.11:2.4.5

spark-defaults.conf 中,我收到此错误:

20/02/26 11:20:45 ERROR spark.SparkContext: 
Failed to add file:/root/.ivy2/jars/org.apache.avro_avro-mapred-1.8.2.jar to Spark environment
java.io.FileNotFoundException: Jar /root/.ivy2/jars/org.apache.avro_avro-mapred-1.8.2.jar not found
at org.apache.spark.SparkContext.addJarFile$1(SparkContext.scala:1838)
at org.apache.spark.SparkContext.addJar(SparkContext.scala:1868)
at org.apache.spark.SparkContext.$anonfun$new$11(SparkContext.scala:458)
at org.apache.spark.SparkContext.$anonfun$new$11$adapted(SparkContext.scala:458)
at scala.collection.immutable.List.foreach(List.scala:392)
at org.apache.spark.SparkContext.<init>(SparkContext.scala:458)
at org.apache.spark.SparkContext$.getOrCreate(SparkContext.scala:2520)
at org.apache.spark.sql.SparkSession$Builder.$anonfun$getOrCreate$5(SparkSession.scala:935)
at scala.Option.getOrElse(Option.scala:189)
at org.apache.spark.sql.SparkSession$Builder.getOrCreate(SparkSession.scala:926)
at org.apache.spark.repl.Main$.createSparkSession(Main.scala:106)

因为 spark-shell 无法同时处理分类器和捆绑包依赖关系,请参阅 https://github.com/apache/spark/pull/21339 和 https://github.com/apache/spark/pull/17416

分类器问题的解决方法如下所示:

$ cp .../.ivy2/jars/org.apache.avro_avro-mapred-1.8.2-hadoop2.jar .../.ivy2/jars/org.apache.avro_avro-mapred-1.8.2.jar

但 DevOps 不会接受这一点。

完整的依赖列表如下所示(为了更好的可读性,我添加了换行符)

root@a5a04d888f85:/opt/spark-2.4.5/conf# cat spark-defaults.conf
spark.jars.packages=com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.9.10,
com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.10,
org.apache.spark:spark-hive_2.11:2.4.5,
org.apache.spark:spark-sql-kafka-0-10_2.11:2.4.5,
org.apache.hadoop:hadoop-aws:2.10.0,
io.delta:delta-core_2.11:0.5.0,
org.postgresql:postgresql:42.2.5,
mysql:mysql-connector-java:8.0.18,
com.datastax.spark:spark-cassandra-connector_2.11:2.4.3,
io.prestosql:presto-jdbc:307

(一切正常 - 除了 Hive)

Spark 2.4.5 和 Hadoop 2.10 的组合是否可以在任何地方使用?怎么样? 如何将 Spark 2.4.5 与用户提供的 Hadoop 和 Hadoop 2.9 或 2.10 结合起来? 是否有必要构建 Spark 来解决 Hive 依赖问题?

【问题讨论】:

对有关预构建版本的评论感到好奇。我只看到 Hadoop 2.6 和 Hadoop 2.7 的预构建二进制文件,但这表明可用性是 Hadoop 2.7 和 Hadoop 2.8。这是一个错误的错误,还是发生了一些变化? 我想将我的 hadoop aws 升级到 3.2。目前坚持对 hadoop 2.7 的火花依赖。是否可以遮蔽hadoop aws?我将使用 uber jar。 @Knight71 它可能适用于您的情况。然而,根据我的经验,这通常会导致问题,尤其是在 AWS 依赖项的情况下。正是出于这个原因,我构建了 Spark(具有一致的)依赖关系。 Spark 集群在 2.2.1 中,预构建了 hadoop 2.7。它不起作用,因为 2.7 jars 已经存在于类路径中。获取 hadoop 配置的 ClassNotFound 错误。 【参考方案1】:

似乎没有一种简单的方法来配置 Spark 2.4.5 和用户提供的 Hadoop 以使用 Hadoop 2.10.0

因为我的任务实际上是最小化依赖问题,所以我选择了compile Spark 2.4.5 与 Hadoop 2.10.0。

./dev/make-distribution.sh \
  --name hadoop-2.10.0 \
  --tgz \
  -Phadoop-2.7 -Dhadoop.version=hadoop-2.10.0 \
  -Phive -Phive-thriftserver \
  -Pyarn

现在 Maven 处理 Hive 依赖项/分类器,生成的包可以使用了。

在我个人看来,编译 Spark 实际上比使用用户提供的 Hadoop 配置 Spark 更容易

到目前为止,集成测试没有显示任何问题,Spark 可以访问 HDFS 和 S3 (MinIO)。

2021-04-08 更新

如果您想添加对 Kubernetes 的支持,只需将 -Pkubernetes 添加到参数列表中

【讨论】:

这种方法看起来不错。我成功地对 Hadoop 2.8.5 的目标版本做了同样的事情。为了更加放心,我比较了 Spark 构建配置文件中每个覆盖的版本,发现它们根本没有改变。我怀疑 Hadoop 2.10.0 也是如此。设置 -Dhadoop.version 似乎不会影响编译,只会影响捆绑的依赖项,这是您在自定义 your-own-Hadoop 版本时手动调整的内容,方法是从选定的 hadoop 版本中放入 jar 包。这只是允许构建系统为您完成这项工作。 这似乎也是使用目标 Hadoop 版本构建的文档提供的方法。值得仔细研究这些方向 - 否则您会错过设置 MAVEN_OPTS 以解决构建的内存要求等内容! spark.apache.org/docs/latest/…【参考方案2】:

假设您不想运行 Spark-on-YARN —— 从 bundle "Spark 2.4.5 with Hadoop 2.7" 开始,然后挑选 Hadoop 库从 bundle “Hadoop 2.10.x”

    丢弃 spark-yarn / hadoop-yarn-* / hadoop-mapreduce-client-* JAR,因为您不需要它们,除了 hadoop-mapreduce-client-core 被 HDFS 和 S3 上的写操作引用(参见“MR提交程序”V1 或 V2) 您还可以丢弃 spark-mesos / mesos-* 和/或 spark-kubernetes / kubernetes-* JAR,具体取决于您计划运行 Spark 的对象 如果您不打算运行“thrift server”实例,您也可以丢弃spark-hive-thriftserverhive-* JARS,除了 hive-metastore 是必要的,正如您可能猜到的那样,管理 Metastore (常规 Hive Metastore 服务或 Spark 会话中的嵌入式 Metastore) 丢弃hadoop-hdfs / hadoop-common / hadoop-auth / hadoop-annotations / htrace-core* / xercesImpl JAR 替换为hadoop-hdfs-client/hadoop-common/hadoop-auth/hadoop-annotations/htrace-core*/xercesImpl/stax2-api 来自 Hadoop 2.10 的 JAR(在 @9876543445@@ 和 @98765454 下)和hdfs/lib/) 从 Hadoop 2.10 添加 S3A 连接器,即 hadoop-aws / jets3t / woodstox-core JAR(在 tools/lib/ 下) 从 Amazon 下载 aws-java-sdk(我猜它不是 Apache 许可证,因此不能与 Hadoop 捆绑) 最后,运行大量测试...

这对我有用,经过一些试验和错误 - 需要注意的是:我针对 S3 兼容的存储系统运行我的测试,但不是针对“真正的”S3,而不是针对常规 HDFS .并且没有“真正的”Hive Metastore 服务,只有 Spark 默认运行的嵌入式内存和易失性 Metastore。


作为记录,该过程与 Spark 3.0.0 预览版和 Hadoop 3.2.1 相同,不同之处在于 你还得升级guava 您不必升级xercesImplhtrace-corestax2-api 你不再需要jets3t 您需要保留更多 hadoop-mapreduce-client-* JAR(可能是因为新的“S3 提交者”)

【讨论】:

不认为您有一个 bash 脚本来设置它? ;) 我的 client 拥有该脚本......而且他们非常固执地不分享任何内容,无论出于何种原因。 嗯。在 Ansible/Chef 中重写所述脚本? :) 感谢您非常详细的回答。所以确实不容易。我今天会进行一些测试,稍后再提供反馈。

以上是关于如何使用用户提供的 Hadoop 正确配置 Spark 2.4的主要内容,如果未能解决你的问题,请参考以下文章

如何配置 Undertow 处理程序以支持正确重写 SPA 书签?

处理django rest framework + vue SPA auth

如何使用 React 和 Firebase 托管在 SPA 上提供 robots.txt?

处理 django rest framework + vue SPA auth

使用 SPA 为授权代码流配置 Identity Server 3 的正确方法是啥?

如何使用 Firebase 托管为 React SPA 提供 404 页面?