hadoop No FileSystem for scheme:file

我试图运行一个简单的NaiveBayesClassifer使用hadoop,得到这个错误

 Exception in thread "main" java.io.IOException: No FileSystem for scheme: file at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:1375) at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:66) at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:1390) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:196) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:95) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:180) at org.apache.hadoop.fs.Path.getFileSystem(Path.java:175) at org.apache.mahout.classifier.naivebayes.NaiveBayesModel.materialize(NaiveBayesModel.java:100) 

代码:

  Configuration configuration = new Configuration(); NaiveBayesModel model = NaiveBayesModel.materialize(new Path(modelPath), configuration);// error in this line.. 

modelPath指向NaiveBayes.bin文件,configuration对象正在打印 – Configuration: core-default.xml, core-site.xml

我认为它是因为jar子,有什么想法?

这是maven-assembly插件破坏事件的典型案例。

为什么这发生在我们身上

不同的JAR( LocalFileSystem hadoop-hdfsDistributedFileSystem hadoop-hdfs )在它们的META-INFO/services目录中包含一个名为org.apache.hadoop.fs.FileSystem的不同文件。 该文件列出了他们要声明的文件系统实现的规范类名(这称为通过java.util.ServiceLoader实现的服务提供者接口,参见org.apache.hadoop.FileSystem 2622行 )。

当我们使用maven-assembly-plugin ,它把我们所有的JAR合并成一个,所有的META-INFO/services/org.apache.hadoop.fs.FileSystem都会相互覆盖。 只剩下其中一个文件(最后一个被添加)。 在这种情况下,来自hadoop-commonsFileSystem列表将覆盖来自hadoop-hdfs的列表,因此DistributedFileSystem不再被声明。

我们如何解决它

在加载Hadoopconfiguration之后,在做任何与FileSystem相关的事情之前,我们称之为:

  hadoopConfig.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName() ); hadoopConfig.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName() ); 

对于那些使用阴影插件的人,遵循david_p的build议,可以通过将ServicesResourceTransformer添加到插件configuration来合并阴影的jar中的服务:

  <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> </transformers> </configuration> </execution> </executions> </plugin> 

这将在一个文件中合并所有的org.apache.hadoop.fs.FileSystem服务

为了logging,这仍然在hadoop 2.4.0发生。 太令人沮丧了

我能够按照此链接中的说明: http : //grokbase.com/t/cloudera/scm-users/1288xszz7r/no-filesystem-for-scheme-hdfs

我将以下内容添加到了我的core-site.xml中,并且它工作正常:

 <property> <name>fs.file.impl</name> <value>org.apache.hadoop.fs.LocalFileSystem</value> <description>The FileSystem for file: uris.</description> </property> <property> <name>fs.hdfs.impl</name> <value>org.apache.hadoop.hdfs.DistributedFileSystem</value> <description>The FileSystem for hdfs: uris.</description> </property> 

谢谢david_p,scala

 conf.set("fs.hdfs.impl", classOf[org.apache.hadoop.hdfs.DistributedFileSystem].getName); conf.set("fs.file.impl", classOf[org.apache.hadoop.fs.LocalFileSystem].getName); 

要么

 <property> <name>fs.hdfs.impl</name> <value>org.apache.hadoop.hdfs.DistributedFileSystem</value> </property> 

花了我很多时间来解决Spark 2.0.2,但这是我的一点:

 val sparkBuilder = SparkSession.builder .appName("app_name") .master("local") // Various Params .getOrCreate() val hadoopConfig: Configuration = sparkBuilder.sparkContext.hadoopConfiguration hadoopConfig.set("fs.hdfs.impl", classOf[org.apache.hadoop.hdfs.DistributedFileSystem].getName) hadoopConfig.set("fs.file.impl", classOf[org.apache.hadoop.fs.LocalFileSystem].getName) 

和我的build.sbt的相关部分:

 scalaVersion := "2.11.8" libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.2" 

我希望这可以帮助!

我使用sbt程序集打包我的项目。 我也遇到这个问题。 我的解决scheme在这里。 第一步:在build.sbt中添加META-INF mergestrategy

 case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard case PathList("META-INF", ps @ _*) => MergeStrategy.first 

第二步:将hadoop-hdfs lib添加到build.sbt

 "org.apache.hadoop" % "hadoop-hdfs" % "2.4.0" 

第三步:清洁; sbt大会

希望以上信息可以帮助你。

假设你正在使用hadoop的mvn和cloudera分布。 我使用cdh4.6并添加这些依赖关系为我工作。我想你应该检查hadoop和mvn依赖的版本。

 <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-core</artifactId> <version>2.0.0-mr1-cdh4.6.0</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.0.0-cdh4.6.0</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>2.0.0-cdh4.6.0</version> </dependency> 

不要忘记添加cloudera mvn仓库。

 <repository> <id>cloudera</id> <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url> </repository> 

对于maven,只需添加hadoop-hdfs的maven依赖项(请参阅下面的链接)将解决问题。

http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.7.1

我假设你使用maven构build示例。

请检查您尝试运行的JAR的内容。 特别是META-INFO/services目录,文件org.apache.hadoop.fs.FileSystem 。 应该有filsystem实现类的列表。 检查行org.apache.hadoop.hdfs.DistributedFileSystem存在于HDFS列表中, org.apache.hadoop.fs.LocalFileSystem于本地文件系统中。

如果是这种情况,则必须在构build过程中重写引用的资源。

其他的可能性是你的类path中没有hadoop-hdfs.jar ,但这个概率很低。 通常如果你有正确的hadoop-client依赖它不是一个选项。

另一个可能的原因(尽pipeOP问题本身并不受此影响)是如果您创build一个不加载默认值的configuration实例:

 Configuration config = new Configuration(false); 

如果你不加载默认值,那么你将不会得到FileSystem实现的默认设置,当试图访问HDFS时会导致类似的错误。 切换到传入true的无参构造函数来加载默认值可能会解决这个问题。

另外,如果您将自定义configuration位置(例如在文件系统上)添加到Configuration对象,请注意您使用的addResource()的哪个重载。 例如,如果您使用addResource(String)则Hadoop假定该string是类path资源,如果您需要指定本地文件,请尝试以下操作:

 File configFile = new File("example/config.xml"); config.addResource(new Path("file://" + configFile.getAbsolutePath())); 

由于我的新手,我花了一些时间来弄清答案。 如果有人从一开始就需要帮助,这就是我想出来的:

 import org.apache.spark.SparkContext import org.apache.spark.SparkConf object MyObject { def main(args: Array[String]): Unit = { val mySparkConf = new SparkConf().setAppName("SparkApp").setMaster("local[*]").set("spark.executor.memory","5g"); val sc = new SparkContext(mySparkConf) val conf = sc.hadoopConfiguration conf.set("fs.hdfs.impl", classOf[org.apache.hadoop.hdfs.DistributedFileSystem].getName) conf.set("fs.file.impl", classOf[org.apache.hadoop.fs.LocalFileSystem].getName) 

我正在使用Spark 2.1

我在build.sbt有这个部分

 assemblyMergeStrategy in assembly := { case PathList("META-INF", xs @ _*) => MergeStrategy.discard case x => MergeStrategy.first } 

如果你使用sbt

 //hadoop lazy val HADOOP_VERSION = "2.8.0" lazy val dependenceList = Seq( //hadoop //The order is important: "hadoop-hdfs" and then "hadoop-common" "org.apache.hadoop" % "hadoop-hdfs" % HADOOP_VERSION ,"org.apache.hadoop" % "hadoop-common" % HADOOP_VERSION ) 
 Configuration conf = new Configuration(); conf.set("fs.defaultFS", "hdfs://nameNode:9000"); FileSystem fs = FileSystem.get(conf); 

设置fs.defaultFS为我工作! Hadoop的2.8.1

使用这个插件

 <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>1.5</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>allinone</shadedClassifierName> <artifactSet> <includes> <include>*:*</include> </includes> </artifactSet> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"> <resource>reference.conf</resource> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> </transformer> <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"> </transformer> </transformers> </configuration> </execution> </executions> </plugin>