Jupyter笔记本、Pyspark、Hadoop-AWS问题

3

我正在尝试使用Jupyter,PySpark和S3文件(通过s3a协议)进行工作。我们需要使用s3会话令牌,因此需要org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider。该组件已添加到hadoop-aws 2.8.3+中。以下是我的尝试代码:

import os
from pyspark.sql import SparkSession

os.environ['PYSPARK_SUBMIT_ARGS'] = '--packages org.apache.hadoop:hadoop-aws:3.0.0 pyspark-shell'
spark = SparkSession.builder.appName('abc2').getOrCreate()
sc = spark.sparkContext
res = sc._jvm.java.lang.Class.forName("org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider")

这个出现了问题:

该操作失败了。

Py4JJavaError: An error occurred while calling z:java.lang.Class.forName.
: java.lang.ClassNotFoundException: org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)

然而,这个类在hadoop-aws 3.0.0中确实存在。

Spark配置显示:

[('spark.driver.port', '34723'),
 ('spark.executor.id', 'driver'),
 ('spark.driver.host', 'HeartyX'),
 ('spark.jars',
  'file:///home/ashic/.ivy2/jars/org.apache.hadoop_hadoop-aws-3.0.0.jar,file:///home/ashic/.ivy2/jars/com.amazonaws_aws-java-sdk-bundle-1.11.199.jar'),
 ('spark.submit.pyFiles',
  '/home/ashic/.ivy2/jars/org.apache.hadoop_hadoop-aws-3.0.0.jar,/home/ashic/.ivy2/jars/com.amazonaws_aws-java-sdk-bundle-1.11.199.jar'),
 ('spark.repl.local.jars',
  'file:///home/ashic/.ivy2/jars/org.apache.hadoop_hadoop-aws-3.0.0.jar,file:///home/ashic/.ivy2/jars/com.amazonaws_aws-java-sdk-bundle-1.11.199.jar'),
 ('spark.rdd.compress', 'True'),
 ('spark.serializer.objectStreamReset', '100'),
 ('spark.app.id', 'local-1542373156862'),
 ('spark.master', 'local[*]'),
 ('spark.submit.deployMode', 'client'),
 ('spark.app.name', 'abc2'),
 ('spark.ui.showConsoleProgress', 'true'),
 ('spark.files',
  'file:///home/ashic/.ivy2/jars/org.apache.hadoop_hadoop-aws-3.0.0.jar,file:///home/ashic/.ivy2/jars/com.amazonaws_aws-java-sdk-bundle-1.11.199.jar')]

所以这些jar包正在被提交。

在一个独立的没有安装hadoop的spark集群上(版本为2.3.1),当使用命令行上的spark-submit时,它可以完美地运行。然而,在Jupyter Notebooks中,似乎找不到所需的类,因此那段代码(以及试图从s3a://bucket/prefix/key读取数据的代码)会失败。

有任何想法为什么--packages jars在jupyter中不可见吗?

更新

所以,我尝试了简化的方法。我创建了一个conda环境,通过pip安装了pyspark 2.4.0(python 3)。然后尝试:

pyspark --packages org.apache.hadoop:hadoop-aws:3.0.0

在启动的终端中,我尝试了上面的代码。在启动时,我看到它下载了jars,但是它仍然找不到类。
更新2
所以,我手动将jars复制到/home/ashic/.conda/envs/pyspark/lib/python3.7/site-packages/pyspark/jars,然后在命令行上运行pyspark。它“只是工作了”。然而,将jars放入文件夹并使用--driver-class-path或者--jars也都不起作用。看起来pyspark没有按预期使用这些jars。

引用:启动SparkContext / SparkSession和相应的JVM之前。这可能会成为一个问题吗? - 10465355
在启动Spark会话之前,我正在设置环境变量,并且上下文配置显示相关的JAR包在列表中。因此,我认为这些都已经被提供了。我想知道驱动程序是否无法访问软件包中的内容(即可能只有执行程序可以)。 - ashic
你添加了哪些jar包到文件夹中?只有hadoop-aws-3.0.0.jar吗?还是我需要所有的hadoop-*-3.0.0.jar文件? - sid-kap
1个回答

1
混合使用不同版本的Hadoop JAR包注定会失败。即使hadoop-* JAR包匹配,您仍会发现版本问题。正确设置类路径是整个ASF大数据堆栈的永恒痛点之一。
最简单的方法可能是将 AWS类复制到您自己的库中,在修复它以使其正常工作并针对Hadoop 2.8运行。
您可能需要将对S3AUtils.lookupPassword(conf,key,...)的调用替换为conf.getTrimmed(key,'“),它将获取会话密钥; lookupPassword代码有点更复杂,因为它被设计来处理存储在加密JCEKS文件中的秘密。

我知道可能存在的问题,并已测试配置以确保其正常工作。问题在于,如果我将jar文件放在pip-installed-pyspark的jar文件夹中,则可以找到它们。但是运行pyspark --jars等命令无法找到该jar文件。复制java文件在这里行不通,因为我正在提交python代码。如果我能告诉它找到我的自定义jar文件,我就可以让它找到hadoop-aws和aws-sdk jar文件。问题是让jupyter找到通过命令行/其他配置传递的jar文件。 - ashic
Spark通常从预先上传到您的HDFS集群中的.tar.gz文件中粘贴的JAR构建其类路径-每个容器都会下载并执行它。更新它很麻烦:下载、打补丁、上传。 - stevel
问题并不在于Spark,spark-submit工作正常。问题出在Pyspark上。 - ashic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接