我将大量数据上传到S3桶,我希望使用Spark和Zeppelin进行分析/可视化。然而,我仍然坚持从S3加载数据。
我做了一些阅读,以便将它们放在一起,并为我节省血腥的细节。我使用docker container p7hb/docker-spark作为Spark安装,我从S3读取数据的基本测试是from here:
我启动容器以及其中的主进程和从进程。我可以通过查看在端口8080上公开的Spark Master WebUI来验证这项工作。此页面列出了工作人员并在标题下保留了所有失败尝试的日志"已完成的应用程序"。所有这些都处于州FINISHED
。
我在该容器内打开bash
并执行以下操作:
a)按照建议here导出环境变量AWS_ACCESS_KEY_ID
和AWS_SECRET_ACCESS_KEY
。
b)开始spark-shell
。为了访问S3,似乎需要加载一些额外的包。通过SE浏览我特别发现this,它告诉我,我可以使用--packages
参数来加载所述包。基本上我运行spark-shell --packages com.amazonaws:aws-java-sdk:1.7.15,org.apache.hadoop:hadoop-aws:2.7.5
(,对于任意版本的组合)。
c)我运行以下代码
sc.hadoopConfiguration.set("fs.s3a.endpoint", "s3-eu-central-1.amazonaws.com")
sc.hadoopConfiguration.set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")
sc.hadoopConfiguration.set("com.amazonaws.services.s3.enableV4", "true")
val sonnets=sc.textFile("s3a://my-bucket/my.file")
val counts = sonnets.flatMap(line => line.split(" ")).map(word => (word, 1)).reduceByKey(_ + _)
然后我会收到各种不同的错误消息,具体取决于我在2b中选择的版本。
我认为2a)没有问题,b / c如果我不提供错误消息,我会收到错误消息Unable to load AWS credentials from any provider in the chain
。 This is a known error new users seem to make.
在尝试解决问题时,我会从here和there中为两个额外的包选择或多或少的随机版本。 SE上的某个地方我读到了hadoop-aws:2.7应该是正确的选择,因为Spark 2.2基于Hadoop 2.7。据说一个人需要使用aws-java-sdk:1.7和那个版本的hadoop-aws。
不管!我尝试了以下组合
--packages com.amazonaws:aws-java-sdk:1.7.4,org.apache.hadoop:hadoop-aws:2.7.1
,产生常见的错误请求400错误。
许多问题都可能导致该错误,我上面所述的尝试包含了我在此页面上能够找到的所有内容。上面的描述包含s3-eu-central-1.amazonaws.com
作为端点,而其他地方使用s3.eu-central-1.amazonaws.com
。根据{{3}},两个端点名称都应该起作用。我确实试过了。
--packages com.amazonaws:aws-java-sdk:1.7.15,org.apache.hadoop:hadoop-aws:2.7.5
,这两种情况都是最新的微型版本,我收到错误消息java.lang.NoSuchMethodError: com.amazonaws.services.s3.transfer.TransferManager.<init>(Lcom/amazonaws/services/s3/AmazonS3;Ljava/util/concurrent/ThreadPoolExecuto
r;)V
--packages com.amazonaws:aws-java-sdk:1.11.275,org.apache.hadoop:hadoop-aws:2.7.5
,我也得到java.lang.NoSuchMethodError: com.amazonaws.services.s3.transfer.TransferManager.<init>(Lcom/amazonaws/services/s3/AmazonS3;Ljava/util/concurrent/ThreadPoolExecutor;)V
--packages com.amazonaws:aws-java-sdk:1.11.275,org.apache.hadoop:hadoop-aws:2.8.1
,我得到java.lang.IllegalAccessError: tried to access method org.apache.hadoop.metrics2.lib.MutableCounterLong.<init>(Lorg/apache/hadoop/metrics2/MetricsInfo;J)V from class org.apache.hadoop.fs.s3a.S3AInstrumentation
--packages com.amazonaws:aws-java-sdk:1.11.275,org.apache.hadoop:hadoop-aws:2.8.3
,我也得到java.lang.IllegalAccessError: tried to access method org.apache.hadoop.metrics2.lib.MutableCounterLong.<init>(Lorg/apache/hadoop/metrics2/MetricsInfo;J)V from class org.apache.hadoop.fs.s3a.S3AInstrumentation
--packages com.amazonaws:aws-java-sdk:1.8.12,org.apache.hadoop:hadoop-aws:2.8.3
,我也得到java.lang.IllegalAccessError: tried to access method org.apache.hadoop.metrics2.lib.MutableCounterLong.<init>(Lorg/apache/hadoop/metrics2/MetricsInfo;J)V from class org.apache.hadoop.fs.s3a.S3AInstrumentation
--packages com.amazonaws:aws-java-sdk:1.11.275,org.apache.hadoop:hadoop-aws:2.9.0
,我也得到java.lang.NoClassDefFoundError: org/apache/hadoop/fs/StorageStatistics
而且,为了完整起见,当我不提供--packages
参数时,我会java.lang.RuntimeException: java.lang.ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found
。
目前似乎没有任何效果。然而,在这个主题上有很多Q / As,谁知道这样做的方式是什么。这都是本地模式,因此几乎没有其他错误来源。我访问S3的方法必定是错误的。它是如何正确完成的?
所以我又投入了一天,没有任何实际进展。据我所知,从Hadoop 2.6开始,Hadoop不再内置对S3的支持,但它通过其他库加载,这些库不是Hadoop的一部分,完全由它自己管理。除了所有杂乱,我最终想要的图书馆似乎是hadoop-aws
。它有一个网页enter link description here,并带有我称之为权威信息的内容:
hadoop-common和hadoop-aws的版本必须相同。
关于此信息的重要一点是,hadoop-common
实际上附带了Hadoop安装。每个Hadoop安装都有一个相应的jar文件,所以这是一个坚实的起点。我的容器有一个文件/usr/hadoop-2.7.3/share/hadoop/common/hadoop-common-2.7.3.jar
,因此可以假设2.7.3是hadoop-aws
所需的版本。
之后它变得模糊不清。 Hadoop版本2.7.x在内部有一些内容,因此它们与aws-java-sdk
的更新版本不兼容,hadoop-aws
是hadoop-aws:2.7.3
所需的库。互联网上充满了使用版本1.7.4 here的建议,但for example here建议使用版本1.7.14 for 2.7.x。
所以我使用aws-java-sdk:1.7.x
和x
进行了另一次运行,joda-time
范围从4到14.无结果,我总是以错误400,错误请求结束。
我的Hadoop安装${HADOOP_HOME}/share/hadoop/tools/lib
2.9.4。我看过问题是用Hadoop 2.8解决的。我想我会继续使用更新的版本构建我自己的docker容器。
转移到Hadoop 2.8.3。它现在才有效。事实证明,你根本不必乱用JAR。 Hadoop附带了应该用于访问AWS S3的JAR。它们隐藏在{{1}}中,默认情况下不会添加到类路径中。我只是在该目录中加载JARS,如上所述执行我的代码,现在它可以正常工作。
答案 0 :(得分:2)
如您所发现的那样,将AWS SDK JAR与其他任何东西混合搭配都是徒劳的。您需要构建AWS JARs Hadoop的版本,并且构建了Jackson AWS的版本。哦,不要尝试混合任何(不同的amazon- * JAR,不同的hadoop- * JAR,不同的jackson- * JARs);他们全都锁定同步。
对于Spark 2.2.0和Hadoop 2.7,使用AWS 1.7.4工件,并确保如果您使用的是Java 8,那么Joda时间是&gt; 2.8.0,如2.9.4。这可能导致400&#34;糟糕的身份验证问题&#34;。
否则,请尝试Troubleshooting S3A