106

我正在尝试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

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

4

20 回答 20

189

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

为什么这发生在我们身上

不同的 JAR(hadoop-commonsfor LocalFileSystemhadoop-hdfsfor )每个都包含在其目录中DistributedFileSystem调用的不同文件。该文件列出了他们想要声明的文件系统实现的规范类名(这称为通过 实现的服务提供者接口,请参阅 参考资料)。org.apache.hadoop.fs.FileSystemMETA-INFO/servicesjava.util.ServiceLoaderorg.apache.hadoop.FileSystem#loadFileSystems

当我们使用maven-assembly-plugin时,它会将我们所有的 JAR 合并为一个,并META-INFO/services/org.apache.hadoop.fs.FileSystem相互覆盖。这些文件中只剩下一个(最后一个添加的文件)。在这种情况下,FileSystem列表 fromhadoop-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,请在下面查看他的答案

于 2014-01-14T16:37:27.537 回答
73

对于那些使用阴影插件的人,按照 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 服务合并到一个文件中

于 2014-12-17T18:23:01.463 回答
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>
于 2014-08-15T15:28:04.387 回答
9

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

我希望这能有所帮助!

于 2016-11-23T13:15:13.393 回答
8

谢谢 david_p,斯卡拉

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>
于 2014-07-23T07:40:20.220 回答
7

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

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

于 2015-09-09T09:59:47.137 回答
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>
于 2014-04-18T13:29:53.520 回答
4

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

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

Step2:将 hadoop-hdfs lib 添加到 build.sbt

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

第三步:sbt clean;sbt 组装

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

于 2014-05-22T15:05:11.320 回答
2

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

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

如果是这种情况,您必须在构建期间覆盖引用的资源。

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

于 2013-08-31T17:51:53.947 回答
2

我遇到了同样的问题。我找到了两个解决方案:(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>
于 2019-09-29T11:07:52.800 回答
2

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

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()));
于 2016-02-10T14:46:34.590 回答
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)
  }
}
于 2018-02-19T07:01:10.120 回答
1
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);

set fs.defaultFS 对我有用!Hadoop-2.8.1

于 2017-08-21T13:27:32.280 回答
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
}
于 2017-03-30T00:24:50.000 回答
1

这个问题很老,但我最近遇到了同样的问题,错误的根源与这里的答案不同。

//在我这边,根本原因是由于 hdfs在路径开头遇到时试图解析权威:

$ hdfs dfs -ls //dev
ls: No FileSystem for scheme: null

因此,请尝试在代码的路径构建部分中查找双斜杠或空变量。

相关 Hadoop 票证:https ://issues.apache.org/jira/browse/HADOOP-8087

于 2021-03-26T10:50:10.293 回答
1

这与 Flink 无关,但我在 Flink 中也发现了这个问题。

对于使用 Flink 的人,需要下载Pre-bundled Hadoop并放入/opt/flink/lib.

于 2020-01-09T12:06:54.430 回答
1

如果您使用的是 Gradle Shadow 插件,那么这是您必须添加的配置:

shadowJar {
    mergeServiceFiles()
}
于 2021-08-23T12:36:07.697 回答
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
)
于 2017-06-06T15:11:41.840 回答
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>
于 2016-01-08T10:10:09.213 回答
-1

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

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 安装。

这为我解决了错误。

于 2017-11-28T12:42:28.410 回答