我正在使用Spark 1.1。 我有一个Spark工作,只在一个存储桶(即以......开头的文件夹)中寻找某种模式的文件夹,并且只应处理那些。我通过以下方式实现这一目标:
FileSystem fs = FileSystem.get(new Configuration(true));
FileStatus[] statusArr = fs.globStatus(new Path(inputPath));
List<FileStatus> statusList = Arrays.asList(statusArr);
List<String> pathsStr = convertFileStatusToPath(statusList);
JavaRDD<String> paths = sc.parallelize(pathsStr);
但是,在Google云端存储路径上运行此作业时:gs:// rsync-1 / 2014_07_31 *(使用最新的Google云存储连接器1.2.9),我收到以下错误:
4/10/13 10:28:38 INFO slf4j.Slf4jLogger: Slf4jLogger started
14/10/13 10:28:38 INFO util.Utils: Successfully started service 'Driver' on port 60379.
14/10/13 10:28:38 INFO worker.WorkerWatcher: Connecting to worker akka.tcp://sparkWorker@hadoop-w-9.c.taboola-qa-01.internal:45212/user/Worker
Exception in thread "main" java.lang.reflect.InvocationTargetException
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.worker.DriverWrapper$.main(DriverWrapper.scala:40)
at org.apache.spark.deploy.worker.DriverWrapper.main(DriverWrapper.scala)
Caused by: java.lang.IllegalArgumentException: Wrong bucket: rsync-1, in path: gs://rsync-1/2014_07_31*, expected bucket: hadoop-config
at com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem.checkPath(GoogleHadoopFileSystem.java:100)
at org.apache.hadoop.fs.FileSystem.makeQualified(FileSystem.java:294)
at com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystemBase.makeQualified(GoogleHadoopFileSystemBase.java:457)
at com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem.getGcsPath(GoogleHadoopFileSystem.java:163)
at com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystemBase.globStatus(GoogleHadoopFileSystemBase.java:1052)
at com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystemBase.globStatus(GoogleHadoopFileSystemBase.java:1027)
at com.doit.customer.dataconverter.Phase0.main(Phase0.java:578)
... 6 more
当我在本地文件夹上运行此作业时,一切正常。
hadoop-config是我用于在Google Compute Engine上部署Spark群集的一个存储桶(使用bdutil 0.35.2工具)
答案 0 :(得分:4)
简答
而不是使用:
FileSystem fs = FileSystem.get(new Configuration(true));
FileStatus[] statusArr = fs.globStatus(new Path(inputPath));
List<FileStatus> statusList = Arrays.asList(statusArr);
你需要做
Path inputPathObj = new Path(inputPath);
FileSystem fs = FileSystem.get(inputPathObj.toUri(), new Configuration(true));
FileStatus[] statusArr = fs.globStatus(inputPathObj);
List<FileStatus> statusList = Arrays.asList(statusArr);
因为在Hadoop中,FileSystem实例是基于URI的scheme
和authority
组件共享的(并且在更高级的设置中可能是用户组信息),并且这些实例在方案之间不可互换和当局。
长答案
这与 [方案]中hostname
的{{1}}和path
组件之间的区别有关:// [权限] / [路径] ,这在HDFS用例中可能更明显,但也适用于GCS。基本上,org.apache.hadoop.fs.FileSystem中有几个URI
方法,其中最适用的方法是:
get
和
public static FileSystem get(Configuration conf)
前者实际上只是用后者调用后者:
public static FileSystem get(URI uri, Configuration conf)
其中 return get(getDefaultUri(conf), conf);
由getDefaultUri(conf)
或fs.default.name
定义。第二个考虑因素是具有不同fs.defaultFS
或hosthname
组件的FileSystems被认为是本质上不同的文件系统;在HDFS案例中,这是有道理的,如:
authority
在可能完全不同的文件系统实例上的每个点,在不同的集群上,允许在两个单独的HDFS实例上使用相同的路径名来引用单独的存储名称空间。虽然在机器的“主机名”方面不太透明,但GCS中的 FileSystem.get("hdfs://foo-cluster-namenode/", conf);
FileSystem.get("hdfs://bar-cluster-namenode/", conf);
确实扮演了GCE URI的bucket
组件的角色 - 在Hadoop中,这意味着authority
确实返回当FileSystem.get
相同但不同存储桶的不同实例时,相同的缓存Java FileSystem对象。正如您无法创建HDFS实例并将其指向其他权限一样:
bucket
当您致电 // Can't mix authorities!
FileSystem.get("hdfs://foo/", conf).listStatus(new Path("hdfs://bar/"));
时,您实际上有一个指向FileSystem.get(conf)
的缓存实例,然后使用它来尝试列出gs://hadoop-config/
。
相反,当您知道要操作的路径时,应该是您获取FileSystem实例的时间:
gs://rsync-1