web-dev-qa-db-fra.com

hadoop No FileSystem pour le schéma: fichier

J'essaie de lancer une NaiveBayesClassifer simple en utilisant hadoop, ce qui provoque cette erreur

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)

Code: 

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

modelPath pointe vers le fichier NaiveBayes.bin et l'objet de configuration est en cours d'impression - Configuration: core-default.xml, core-site.xml 

Je pense que c'est à cause des pots, des idées?

76
Mahender Singh

C'est un cas typique du plugin maven-Assembly qui casse des choses.

Pourquoi cela nous est arrivé

Différents JAR (hadoop-commons pour LocalFileSystem, hadoop-hdfs pour DistributedFileSystem) contiennent chacun un fichier différent appelé org.Apache.hadoop.fs.FileSystem dans leur répertoire META-INFO/services. Ce fichier répertorie les noms de classe canoniques des implémentations du système de fichiers qu’ils souhaitent déclarer (l’appelle une interface de fournisseur de services implémentée via Java.util.ServiceLoader, voir org.Apache.hadoop.FileSystemligne 2622 ).

Lorsque nous utilisons maven-Assembly-plugin, tous nos fichiers JAR sont fusionnés en un seul et tous les META-INFO/services/org.Apache.hadoop.fs.FileSystem se écrasent. Un seul de ces fichiers reste (le dernier ajouté). Dans ce cas, la liste FileSystem de hadoop-commons remplace la liste de hadoop-hdfs, de sorte que DistributedFileSystem n'a plus été déclaré.

Comment nous l'avons résolu

Après avoir chargé la configuration Hadoop, mais juste avant de faire quoi que ce soit lié à FileSystem-, nous appelons ceci:

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

Mise à jour: le correctif correct

+krookedking a porté à mon attention qu'il existe un moyen basé sur la configuration pour que le maven-Assembly utilise une version fusionnée de toutes les déclarations de services FileSystem . Ajoutez le plugin suivant à votre fichier 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>
151
david_p

Pour ceux qui utilisent le plugin shade, suivant les conseils de david_p, vous pouvez fusionner les services dans le fichier jar ombré en ajoutant le serviceResourceTransformer à la configuration du plugin:

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

Cela va fusionner tous les services org.Apache.hadoop.fs.FileSystem dans un fichier

52
krookedking

Pour mémoire, cela se produit encore dans hadoop 2.4.0. Tellement frustrant...

J'ai pu suivre les instructions de ce lien: http://grokbase.com/t/cloudera/scm-users/1288xszz7r/no-filesystem-for-scheme-hdfs

J'ai ajouté ce qui suit à mon core-site.xml et cela a fonctionné:

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

merci 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);

ou

<property>
 <name>fs.hdfs.impl</name>
 <value>org.Apache.hadoop.hdfs.DistributedFileSystem</value>
</property>
7
Andy

Cela m'a pris du temps pour le comprendre avec Spark 2.0.2, mais voici mon petit mot:

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)

Et les parties pertinentes de mon build.sbt:

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

J'espère que cela peut aider!

7
Mauro Arnoldi

Pour maven, il suffit d'ajouter la dépendance de maven pour hadoop-hdfs (voir le lien ci-dessous) qui résoudra le problème.

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

5
kwky

J'utilise sbt Assembly pour emballer mon projet. Je rencontre aussi ce problème. Ma solution est ici. Étape 1: ajoutez la stratégie de fusion META-INF dans votre build.sbt

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

Étape 2: ajoutez la bibliothèque hadoop-hdfs à build.sbt

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

Step3: sbt propre; sbt assemblée

J'espère que les informations ci-dessus peuvent vous aider.

4
Haimei

En supposant que vous utilisez la distribution mvn et cloudera de hadoop. J'utilise cdh4.6 et l'ajout de ces dépendances a fonctionné pour moi. Je pense que vous devriez vérifier les versions des dépendances hadoop et 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>

n'oubliez pas d'ajouter le référentiel mcln cloudera.

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

Une autre cause possible (bien que la question des OP ne souffre pas de cela) est si vous créez une instance de configuration qui ne charge pas les valeurs par défaut:

Configuration config = new Configuration(false);

Si vous ne chargez pas les paramètres par défaut, vous n'obtiendrez pas les paramètres par défaut pour des applications telles que les implémentations FileSystem, qui entraînent des erreurs identiques, lorsque vous essayez d'accéder à HDFS. Le passage au constructeur sans paramètre de transmission de true pour charger les valeurs par défaut peut résoudre le problème.

De plus, si vous ajoutez des emplacements de configuration personnalisés (par exemple sur le système de fichiers) à l'objet Configuration, faites attention à la surcharge de addResource() que vous utilisez. Par exemple, si vous utilisez addResource(String), Hadoop suppose que la chaîne est une ressource de chemin de classe. Si vous devez spécifier un fichier local, procédez comme suit:

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

Je suppose que vous construisez un échantillon en utilisant maven.

Veuillez vérifier le contenu du fichier JAR que vous essayez d'exécuter. Surtout le répertoire META-INFO/services, le fichier org.Apache.hadoop.fs.FileSystem. Il devrait y avoir une liste des classes d'implémentation de filsystem. La ligne de contrôle org.Apache.hadoop.hdfs.DistributedFileSystem est présente dans la liste pour HDFS et org.Apache.hadoop.fs.LocalFileSystem pour le schéma de fichiers local.

Si tel est le cas, vous devez remplacer la ressource référencée lors de la construction.

Une autre possibilité est que vous n'avez simplement pas hadoop-hdfs.jar dans votre chemin d'accès aux classes, mais cette probabilité est faible. Généralement, si vous avez la dépendance correcte avec hadoop-client, ce n'est pas une option.

2
Roman Nikitchenko

Il m'a fallu un jour pour trouver une solution à partir de réponses données, en raison de ma nouvelle jeunesse. C’est ce que j’ai trouvé, si quelqu'un a besoin d'aide dès le début:

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)

J'utilise Spark 2.1

Et j'ai cette partie dans mon build.sbt

assemblyMergeStrategy in Assembly := {
  case PathList("META-INF", xs @ _*) => MergeStrategy.discard
  case x => MergeStrategy.first
}
1
Akavall
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);

set fs.defaultFS fonctionne pour moi! Hadoop-2.8.1

1
Asran Deng

Si vous utilisez 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
Peluo

Pour SBT, utilisez ci-dessous mergeStrategy dans build.sbt

mergeStrategy in Assembly <<= (mergeStrategy in Assembly) { (old) => {
    case PathList("META-INF", "services", "org.Apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLines
    case s => old(s)
  }
}
0
Asad Raza