hadoop方案无文件系统:文件


96

我正在尝试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: core-default.xml, core-site.xml

我认为是因为罐子,有什么想法吗?


需要更多信息...
Tariq

2
不认识我自己,但是快速浏览一下Google会发现罐子周围存在一些未按您的建议被引用的问题。以下链接可能会给出答案。groups.google.com/a/cloudera.org/forum/#!topic/scm-users/…grokbase.com/t/cloudera/cdh-user/134r64jm5t/…–
Emile

我在类路径中添加了hadoop-common-2.0.0-cdh4.3.0-sources.jar和hadoop-core-0.20.2.jar,我先删除了它,但不知道为什么。
Mahender Singh 2013年

1
嗯..能否请您介绍一下您的环境?另外,请向我显示完整的异常消息。
Tariq 2013年

modelPath的价值是什么?您是否尝试过file:///path/to/dir
克里斯·怀特

Answers:


174

这是maven-assembly插件中断事件的典型情况。

为什么这发生在我们身上

不同的JAR(hadoop-commonsfor LocalFileSystemhadoop-hdfsfor DistributedFileSystem)各自org.apache.hadoop.fs.FileSystem在其META-INFO/services目录中包含一个不同的文件。该文件列出了要声明的文件系统实现的规范类名(这称为通过实现的服务提供商接口java.util.ServiceLoader,请参见org.apache.hadoop.FileSystem#loadFileSystems)。

当使用时maven-assembly-plugin,它将所有JAR合并为一个,并且全部META-INFO/services/org.apache.hadoop.fs.FileSystem覆盖彼此。这些文件仅保留其中一个(添加的最后一个)。在这种情况下,FileSystemfrom hadoop-commons的列表会覆盖from 的列表hadoop-hdfs,因此DistributedFileSystem不再声明。

我们如何解决它

在加载Hadoop配置之后,但在进行任何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()
    );

更新:正确的修复

引起我注意的是krookedking,有一种基于配置的方法可以maven-assembly使用所有FileSystem服务声明的合并版本,请在下面查看他的答案


13
这是在Spark中执行相同操作所需的等效代码: val hadoopConfig: Configuration = spark.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)
Philip O.14年

8
实际上,我只是将此Maven依赖项添加http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.2.0到了Maven中并解决了问题。
宝马先生

6
我尝试添加hadoop-hdfs,hadoop-core,hadoop-common,hadoop-client,Aslo尝试添加hadoopConfig.set(“ fs.hdfs.impl”,org.apache.hadoop.hdfs.DistributedFileSystem.class.getName() ); hadoopConfig.set(“ fs.file.impl”,org.apache.hadoop.fs.LocalFileSystem.class.getName()); 但不起作用,从eclipse运行时运行正常,但是从java -cp命令运行时,显示上述错误
Harish Pathak

1
Harish,您看到了什么?这里有同样的问题,但有intellij
ThommyH '16

只是一个很好的答案的补充:如果使用的是hadoop JARS但在非hadoop集群中运行作业,则“”“ hadoopConfig.set(” fs.hdfs.impl .....“”“”不会在这种情况下,我们将退回到管理程序集的构建,例如在sbt中,我们可以执行concat甚至filterDistinctLines的mergeStrategy
人类,

62

对于使用shade插件的用户,按照david_p的建议,您可以通过将ServicesResourceTransformer添加到插件配置中来合并阴影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服务合并到一个文件中


3
我最喜欢这个解决方案。在问题(源)上解决问题,而不是在事后用配置更改对问题进行修补。
凯文·保利

1
好答案。修复了我类似的错误。尝试过使用maven-assembly-plugin以及maven-jar-plugin / maven-dependency-plugin组合,但是没有用。该解决方案使我的Spark应用程序正常工作。非常感谢!
somnathchakrabarti

好答案!非常感谢!
andrea.lagala '16

这应该标记为已接受的答案。当jar文件使用META-INF / services目录将接口映射到实现时,必须使用ServicesResourceTransformer。可以在这里找到更多信息:maven.apache.org/plugins/maven-shade-plugin/examples/…–
马里奥(Mario)

极好的答案。
Niranjan Subramanian

9

记录下来,这在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>

8

谢谢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>

1
我只读在此之后我才意识到的conf这里是Hadoop的配置:brucebcampbell.wordpress.com/2014/12/11/...
萨尔

8

花了我很长时间才用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"

希望对您有所帮助!



5

假设您正在使用mvn和cloudera分发的hadoop。我正在使用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>

4

我使用sbt程序集打包我的项目。我也遇到这个问题。我的解决方案在这里。步骤1:在您的build.sbt中添加META-INF合并策略

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清理;sbt汇编

希望以上信息对您有帮助。


15
更好的解决方案可能是合并,例如:case PathList("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLines这将保留所有注册的文件系统
ravwojdyla

感谢@ravwojdyla,非常简洁的解决方案。你救了我的头发。对于迷失的灵魂,发现这个Apache火花的答案。在sbt-assembly正常工作时,将其添加到build.sbt中。
贪婪的编码者,2016年

@ravwojdyla提供的解决方案是唯一对我有用的解决方案。
谢尔盖·科瓦廖夫

2
@ravwojdyla给出的解决方案是理想的。我在build.sbt中做了类似的设置,并使用了:```AssemblyMergeStrategy in assembly:= {case PathList(“ META-INF”,“ MANIFEST.MF”)=> MergeStrategy.discard case PathList(“ META-INF”, “服务”,“ org.apache.hadoop.fs.FileSystem”)=> MergeStrategy.concat案例_ => MergeStrategy.first}```
人类,

2

我假设您使用Maven构建示例。

请检查您要运行的JAR的内容。特别是META-INFO/services目录,文件org.apache.hadoop.fs.FileSystem。应该有filsystem实现类的列表。检查线org.apache.hadoop.hdfs.DistributedFileSystem出现在列表和HDFSorg.apache.hadoop.fs.LocalFileSystem本地文件方案。

在这种情况下,您必须在构建过程中覆盖引用的资源。

另一种可能是您根本不在hadoop-hdfs.jar类路径中,但是可能性很小。通常,如果您具有正确的hadoop-client依赖关系,则不能选择。


HI Roman ..i有相同的问题,而META-INFO / services / org.apache.hadoop.fs.FileSystem没有hdfs行。我有2.0.0-mr1-cdh4.4.0作为唯一依赖项。我需要做什么?关于这个的任何文件吗?使用Maven构建
sethi 2014年

2

另一个可能的原因(尽管OP问题本身并不会因此受到影响)是,如果您创建的配置实例未加载默认值:

Configuration config = new Configuration(false);

如果不加载默认值,那么将无法获得诸如FileSystem实现之类的默认设置,当尝试访问HDFS时会导致类似的错误。切换到传递参数以传递true默认值的无参数构造函数可以解决此问题。

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

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

1

由于我是新手,我花了一些时间从给出的答案中找出解决方法。如果有人从一开始就需要帮助,这就是我想出的:

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
}

1
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);

设置fs.defaultFS对我有用!Hadoop-2.8.1


1

对于SBT,请在build.sbt中的mergeStrategy下使用

mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) => {
    case PathList("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLines
    case s => old(s)
  }
}

0

使用这个插件

<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>

0

如果您正在使用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
)

0

我遇到了同样的问题。我发现了两种解决方案:(1)手动编辑jar文件:

使用WinRar(或类似工具)打开jar文件。转到“ Meta-info”>“ services”,然后通过添加以下内容来编辑“ org.apache.hadoop.fs.FileSystem”:

org.apache.hadoop.fs.LocalFileSystem

(2)如下更改我的依存关系的顺序

<dependencies>
<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-hdfs</artifactId>
  <version>3.2.1</version>
</dependency>

<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-common</artifactId>
  <version>3.2.1</version>
</dependency>

<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-mapreduce-client-core</artifactId>
  <version>3.2.1</version>
</dependency>

<dependency>
  <groupId>org.apache.hadoop</groupId>
  <artifactId>hadoop-client</artifactId>
  <version>3.2.1</version>
</dependency>



</dependencies>


-1

我也遇到类似的问题。添加了core-site.xml和hdfs-site.xml作为conf(对象)资源

Configuration conf = new Configuration(true);    
conf.addResource(new Path("<path to>/core-site.xml"));
conf.addResource(new Path("<path to>/hdfs-site.xml"));

pom.xml中的已编辑版本冲突。(例如,如果hadoop的配置版本为2.8.1,但是在pom.xml文件中,依赖关系的版本为2.7.1,然后将其更改为2.8.1)。再次运行Maven安装。

这为我解决了错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.