hadoop No FileSystem para el esquema: archivo

96

Estoy tratando de ejecutar un simple NaiveBayesClassiferusando hadoop, obteniendo este error

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)

Codigo:

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

modelPathestá apuntando al NaiveBayes.binarchivo, y el objeto de configuración está imprimiendo -Configuration: core-default.xml, core-site.xml

Creo que es por frascos, ¿alguna idea?

Mahender Singh
fuente
Necesito más información ...
Tariq
2
No lo sé, pero un vistazo rápido a Google sugiere que hay algunos problemas relacionados con los frascos que no se mencionan como sugirió. Quizás los siguientes enlaces le den una respuesta. groups.google.com/a/cloudera.org/forum/#!topic/scm-users/… grokbase.com/t/cloudera/cdh-user/134r64jm5t/…
Emile
Estaba agregando hadoop-common-2.0.0-cdh4.3.0-sources.jar y hadoop-core-0.20.2.jar a la ruta de clases, lo eliminé primero y funcionó, no sé por qué.
Mahender Singh
1
Hmm ... ¿Podría hablarme de su entorno? Además, muéstreme el mensaje de excepción completo.
Tariq
¿Cuál es el valor de modelPath? has probadofile:///path/to/dir
Chris White

Respuestas:

174

Este es un caso típico en el que el maven-assemblycomplemento rompe cosas.

¿Por qué nos pasó esto?

Cada uno de los diferentes JAR ( hadoop-commonspara LocalFileSystem, hadoop-hdfspara DistributedFileSystem) contiene un archivo diferente llamado org.apache.hadoop.fs.FileSystemen su META-INFO/servicesdirectorio. Este archivo enumera los nombres de clase canónicos de las implementaciones del sistema de archivos que desean declarar (esto se denomina Interfaz de proveedor de servicios implementada a través de java.util.ServiceLoader, consulte org.apache.hadoop.FileSystem#loadFileSystems).

Cuando lo usamos maven-assembly-plugin, fusiona todos nuestros JAR en uno y todos se META-INFO/services/org.apache.hadoop.fs.FileSystemsobrescriben entre sí. Solo queda uno de estos archivos (el último que se agregó). En este caso, la FileSystemlista de hadoop-commonssobrescribe la lista de hadoop-hdfs, por DistributedFileSystemlo que ya no se declaró.

Como lo arreglamos

Después de cargar la configuración de Hadoop, pero justo antes de hacer algo FileSystemrelacionado, llamamos a esto:

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

Actualización: la solución correcta

Me ha llamado la atención krookedkingque hay una forma basada en la configuración de hacer que el maven-assemblyuso sea una versión combinada de todas las FileSystemdeclaraciones de servicios, consulte su respuesta a continuación.

david_p
fuente
13
Aquí está el código equivalente requerido para hacer lo mismo en 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.28 de
8
En realidad, acabo de agregar esta dependencia http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.2.0maven a maven y el problema se resolvió.
B.Mr.W.
6
Intenté agregar hadoop-hdfs, hadoop-core, hadoop-common, hadoop-client, Aslo intentó agregar hadoopConfig.set ("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName () ); hadoopConfig.set ("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName ()); pero no funciona, cuando se ejecuta desde eclipse funciona bien, pero cuando se ejecuta desde el comando java -cp muestra el error anterior
Harish Pathak
1
Harish, ¿qué has visto? El mismo problema aquí pero con intellij
ThommyH
Solo una adición a la maravillosa respuesta: si uno está usando los JARS de hadoop pero ejecutando el trabajo en un clúster que no es de Hadoop, "" "hadoopConfig.set (" fs.hdfs.impl ..... "" "" no En cuyo caso, recurriremos a la gestión de la compilación del ensamblado. Por ejemplo, en sbt podríamos hacer una combinación de estrategia de concat o incluso filterDistinctLines
humano
62

Para aquellos que usan el complemento de sombra, siguiendo el consejo de david_p, puede fusionar los servicios en el frasco sombreado agregando ServicesResourceTransformer a la configuración del complemento:

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

Esto fusionará todos los servicios org.apache.hadoop.fs.FileSystem en un archivo

krookedking
fuente
3
Me gusta más esta solución. Solucione el problema en la fuente (la compilación) en lugar de parchearlo con cambios de configuración después del hecho.
Kevin Pauli
1
Gran respuesta. Se corrigió mi error similar. Intenté con la combinación maven-assembly-plugin y maven-jar-plugin / maven-dependency-plugin, pero no funcionó. Esta solución hizo que mi aplicación Spark funcionara. ¡Muchas gracias!
somnathchakrabarti
¡Gran respuesta! ¡Muchas gracias!
andrea.lagala
Esto debe marcarse como la respuesta aceptada. ServicesResourceTransformer es necesario cuando los archivos jar mapean interfaces con implementaciones mediante el uso de un directorio META-INF / services. Puede encontrar más información aquí: maven.apache.org/plugins/maven-shade-plugin/examples/…
Mario
Excelente respuesta.
Niranjan Subramanian
9

Para el registro, esto todavía está sucediendo en hadoop 2.4.0. Muy frustrante...

Pude seguir las instrucciones en este enlace: http://grokbase.com/t/cloudera/scm-users/1288xszz7r/no-filesystem-for-scheme-hdfs

Agregué lo siguiente a mi core-site.xml y funcionó:

<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>
Acaya
fuente
8

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

o

<property>
 <name>fs.hdfs.impl</name>
 <value>org.apache.hadoop.hdfs.DistributedFileSystem</value>
</property>
Andy
fuente
1
Sólo después de leer este me di cuenta de que la conf aquí fue la configuración de Hadoop: brucebcampbell.wordpress.com/2014/12/11/...
Sal
8

Me tomó años entenderlo con Spark 2.0.2, pero aquí está mi granito de arena:

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)

Y las partes relevantes de mi build.sbt:

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

¡Espero que esto pueda ayudar!

Mauro Arnoldi
fuente
5

Suponiendo que está utilizando la distribución mvn y cloudera de hadoop. Estoy usando cdh4.6 y agregar estas dependencias funcionó para mí. Creo que debería verificar las versiones de las dependencias de hadoop y 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>

no olvide agregar el repositorio mvn de cloudera.

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

Utilizo el ensamblaje sbt para empaquetar mi proyecto. También me encuentro con este problema. Mi solución está aquí. Paso 1: agregue META-INF mergestrategy en su build.sbt

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

Paso 2: agregue hadoop-hdfs lib a build.sbt

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

Paso 3: sbt clean; montaje sbt

Espero que la información anterior pueda ayudarte.

Haimei
fuente
15
Una mejor solución podría ser fusionar como: case PathList("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLinesEsto mantendrá todos los sistemas de archivos registrados
ravwojdyla
Gracias en @ravwojdyla, solución bastante ordenada. Salvaste mi cabello. Para las almas perdidas que descubren esta respuesta para Apache Spark. Agregue esto a build.sbt cuando sbt-assembly, funcione correctamente.
Codificador codicioso
La solución proporcionada por @ravwojdyla es la única que funcionó para mí.
Sergey Kovalev
2
La solución dada por @ravwojdyla es ideal. Hice una configuración similar en build.sbt y usé: `` assemblyMergeStrategy in assembly: = {case PathList ("META-INF", "MANIFEST.MF") => MergeStrategy.discard case PathList ("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.concat case _ => MergeStrategy.first} `` `
humano
2

Supongo que construye una muestra usando maven.

Verifique el contenido del JAR que está intentando ejecutar. Especialmente META-INFO/servicesdirectorio, archivo org.apache.hadoop.fs.FileSystem. Debería haber una lista de clases de implementación de filsystem. La línea de verificación org.apache.hadoop.hdfs.DistributedFileSystemestá presente en la lista para HDFS y org.apache.hadoop.fs.LocalFileSystempara el esquema de archivo local.

Si este es el caso, debe anular el recurso referido durante la compilación.

Otra posibilidad es que simplemente no la tenga hadoop-hdfs.jaren su classpath, pero esto tiene una probabilidad baja. Por lo general, si tiene la hadoop-clientdependencia correcta, no es una opción.

Roman Nikitchenko
fuente
HI Roman ... tengo el mismo problema y META-INFO / services / org.apache.hadoop.fs.FileSystem no tiene línea hdfs. Tengo 2.0.0-mr1-cdh4.4.0 como única dependencia. ¿Que necesito hacer? ¿Alguna documentación sobre esto? Usando Maven para construir
sethi
2

Otra posible causa (aunque la pregunta de OP en sí misma no sufre de esto) es si crea una instancia de configuración que no carga los valores predeterminados:

Configuration config = new Configuration(false);

Si no carga los valores predeterminados, no obtendrá la configuración predeterminada para cosas como las FileSystemimplementaciones que conducen a errores idénticos como este al intentar acceder a HDFS. Cambiar al constructor sin parámetros de pasar truea cargar valores predeterminados puede resolver esto.

Además, si está agregando ubicaciones de configuración personalizadas (por ejemplo, en el sistema de archivos) al Configurationobjeto, tenga cuidado con la sobrecarga addResource()que usa. Por ejemplo, si usa addResource(String)Hadoop asume que la cadena es un recurso de ruta de clase, si necesita especificar un archivo local, intente lo siguiente:

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

Me tomó algún tiempo encontrar la solución a partir de las respuestas dadas, debido a mi falta de experiencia. Esto es lo que se me ocurrió, si alguien más necesita ayuda desde el principio:

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)

Estoy usando Spark 2.1

Y tengo esta parte en mi build.sbt

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

set fs.defaultFS funciona para mí! Hadoop-2.8.1

Asran Deng
fuente
1

Para SBT, use debajo de mergeStrategy en 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)
  }
}
Asad Raza
fuente
0

Utilice este complemento

<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>
Harish Pathak
fuente
0

Si está utilizando 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
)
Peluo
fuente
0

Me enfrenté al mismo problema. Encontré dos soluciones: (1) Editar el archivo jar manualmente:

Abra el archivo jar con WinRar (o herramientas similares). Vaya a Meta-info> servicios y edite "org.apache.hadoop.fs.FileSystem" agregando:

org.apache.hadoop.fs.LocalFileSystem

(2) Cambiar el orden de mis dependencias de la siguiente manera

<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>
Mohammad-Ali
fuente
0

Esto no está relacionado con Flink, pero también encontré este problema en Flink.

Para las personas que usan Flink, deben descargar Hadoop incluido y ponerlo en su interior /opt/flink/lib.

David Magalhães
fuente
-1

También me encontré con un problema similar. Se agregaron core-site.xml y hdfs-site.xml como recursos de conf (objeto)

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

También conflictos de versiones editadas en pom.xml. (por ejemplo, si la versión configurada de hadoop es 2.8.1, pero en el archivo pom.xml, las dependencias tienen la versión 2.7.1, luego cámbiela a 2.8.1) Ejecute la instalación de Maven nuevamente.

Este error me solucionó.

Raxit Solanki
fuente