我试图使用hadoop运行一个简单的NaiveBayesClassifer
,得到这个错误
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
我认为这是因为罐子,任何想法?
这是maven-Assembly
插件破坏事物的典型案例。
不同的JAR(LocalFileSystem
的hadoop-commons
,DistributedFileSystem
的hadoop-hdfs
)在org.Apache.hadoop.fs.FileSystem
目录中都包含一个名为META-INFO/services
的不同文件。此文件列出了他们要声明的文件系统实现的规范类名(这称为通过Java.util.ServiceLoader
实现的服务提供者接口,请参阅org.Apache.hadoop.FileSystem
第2622行 )。
当我们使用maven-Assembly-plugin
时,它会将我们所有的JAR合并为一个,并且所有META-INFO/services/org.Apache.hadoop.fs.FileSystem
都会相互覆盖。只剩下其中一个文件(最后添加的文件)。在这种情况下,hadoop-commons
中的FileSystem
列表会覆盖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
服务声明的合并版本。将以下插件添加到pom.xml
文件中:
<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>
对于那些使用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服务合并到一个文件中
为了记录,这仍然发生在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"
我希望这可以帮助你!
对于maven,只需为hadoop-hdfs添加maven依赖项(请参阅下面的链接)即可解决问题。
http://mvnrepository.com/artifact/org.Apache.hadoop/hadoop-hdfs/2.7.1
我使用sbt Assembly打包我的项目。我也遇到了这个问题。我的解决方案在这里。第1步:在build.sbt中添加META-INF mergestrategy
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
case PathList("META-INF", ps @ _*) => MergeStrategy.first
第2步:将hadoop-hdfs lib添加到build.sbt
"org.Apache.hadoop" % "hadoop-hdfs" % "2.4.0"
第3步:干净;大会
希望以上信息可以帮到你。
假设你正在使用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>
另一个可能的原因(虽然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()));
我假设你使用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
依赖,那么它不是一个选项。
对于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)
}
}
由于我的新手,我花了一些时间从给定的答案中找出解决方法。这就是我提出的,如果其他人从一开始就需要帮助:
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
}
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);
设置fs.defaultFS适合我! Hadoop的2.8.1
如果你正在使用 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
)