我试图让我的Spark Streaming应用程序从S3目录中读取他的输入,但是在使用spark-submit脚本启动它之后我一直收到此异常:
Exception in thread "main" java.lang.IllegalArgumentException: AWS Access Key ID and Secret Access Key must be specified as the username or password (respectively) of a s3n URL, or by setting the fs.s3n.awsAccessKeyId or fs.s3n.awsSecretAccessKey properties (respectively).
at org.apache.hadoop.fs.s3.S3Credentials.initialize(S3Credentials.java:66)
at org.apache.hadoop.fs.s3native.Jets3tNativeFileSystemStore.initialize(Jets3tNativeFileSystemStore.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:82)
at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:59)
at org.apache.hadoop.fs.s3native.$Proxy6.initialize(Unknown Source)
at org.apache.hadoop.fs.s3native.NativeS3FileSystem.initialize(NativeS3FileSystem.java:216)
at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:1386)
at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:66)
at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:1404)
at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:254)
at org.apache.hadoop.fs.Path.getFileSystem(Path.java:187)
at org.apache.spark.streaming.StreamingContext.checkpoint(StreamingContext.scala:195)
at MainClass$.main(MainClass.scala:1190)
at MainClass.main(MainClass.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.spark.deploy.SparkSubmit$.launch(SparkSubmit.scala:292)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:55)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
我按照http://spark.apache.org/docs/latest/ec2-scripts.html(页面底部)建议的代码块设置这些变量:
val ssc = new org.apache.spark.streaming.StreamingContext(
conf,
Seconds(60))
ssc.sparkContext.hadoopConfiguration.set("fs.s3n.awsAccessKeyId",args(2))
ssc.sparkContext.hadoopConfiguration.set("fs.s3n.awsSecretAccessKey",args(3))
args(2)和args(3)当然是我的AWS Access Key ID和Secrete Access Key。
为什么一直说他们没有定?
编辑:我也尝试过这种方式,但我得到了同样的例外:
val lines = ssc.textFileStream("s3n://"+ args(2) +":"+ args(3) + "@<mybucket>/path/")
答案 0 :(得分:24)
奇。尝试在.set
上执行sparkContext
。尝试在启动应用程序之前导出env变量:
export AWS_ACCESS_KEY_ID=<your access>
export AWS_SECRET_ACCESS_KEY=<your secret>
^^这就是我们这样做的方式。
更新:根据@tribbloid,上面打破了1.3.0,现在你必须使用hdfs-site.xml进行年龄和年龄的讨论,或者你可以这样做(这可以在spark-shell中运行):< / p>
val hadoopConf = sc.hadoopConfiguration;
hadoopConf.set("fs.s3.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId", myAccessKey)
hadoopConf.set("fs.s3.awsSecretAccessKey", mySecretKey)
答案 1 :(得分:22)
以下配置适用于我,请确保您还设置“fs.s3.impl”:
val conf = new SparkConf().setAppName("Simple Application").setMaster("local")
val sc = new SparkContext(conf)
val hadoopConf=sc.hadoopConfiguration;
hadoopConf.set("fs.s3.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId",myAccessKey)
hadoopConf.set("fs.s3.awsSecretAccessKey",mySecretKey)
答案 2 :(得分:3)
在AWS EMR上,上述建议无效。相反,我更新了conf / core-site.xml中的以下属性:
带有S3凭据的fs.s3n.awsAccessKeyId和fs.s3n.awsSecretAccessKey。
答案 3 :(得分:3)
对于那些使用EMR的人,使用https://github.com/awslabs/emr-bootstrap-actions/tree/master/spark中描述的Spark构建,并使用s3:// URI引用S3。无需设置S3实施或其他配置,因为凭据由IAM或角色设置。
答案 4 :(得分:2)
最新的EMR版本(在4.6.0上测试)需要以下配置:
val sc = new SparkContext(conf)
val hadoopConf = sc.hadoopConfiguration
hadoopConf.set("fs.s3.impl", "com.amazon.ws.emr.hadoop.fs.EmrFileSystem")
hadoopConf.set("fs.s3.awsAccessKeyId", myAccessKey)
hadoopConf.set("fs.s3.awsSecretAccessKey", mySecretKey)
虽然在大多数情况下,开箱即用的配置应该可以正常工作 - 如果您使用与启动集群的S3凭据不同,则可以使用。
答案 5 :(得分:0)
这在1.4.1 shell中适用于我:
val conf = sc.getConf
conf.set("spark.hadoop.fs.s3.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem")
conf.set("spark.hadoop.fs.s3.awsAccessKeyId", <your access key>)
conf.set("spark.hadoop.fs.s3.awsSecretAccessKey", <your secret key>)
SparkHadoopUtil.get.conf.addResource(SparkHadoopUtil.get.newConfiguration(conf))
...
sqlContext.read.parquet("s3://...")
答案 6 :(得分:0)
增加@ nealmcb的答案,最直接的方法是定义
HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
<{1>}中的或导出conf/spark-env.sh
或~/.bashrc
中的env变量。
只要您可以通过hadoop访问s3,这将有效。例如,如果你可以运行
~/.bash_profile
然后hadoop可以看到s3路径。
如果hadoop无法查看路径,请按照How can I access S3/S3n from a local Hadoop 2.6 installation?
中的建议操作答案 7 :(得分:0)
在Java中,以下是代码行。您只需要在SparkContext中添加AWS凭证,而不必在SparkSession中添加。
JavaSparkContext sc = new JavaSparkContext(spark.sparkContext());
sc.hadoopConfiguration().set("fs.s3a.access.key", AWS_KEY);
sc.hadoopConfiguration().set("fs.s3a.secret.key", AWS_SECRET_KEY);