hadoop Sem FileSystem para o esquema: arquivo

96

Estou tentando executar um simples NaiveBayesClassiferusando o hadoop, obtendo este erro

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)

Código:

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

modelPathestá apontando para o NaiveBayes.binarquivo e o objeto de configuração está sendo impresso -Configuration: core-default.xml, core-site.xml

Acho que é por causa dos potes, alguma ideia?

Mahender Singh
fonte
Precisa de mais informações ...
Tariq
2
Não me conheço, mas uma rápida olhada no google sugere que existem alguns problemas em torno dos jars não sendo referenciados como você sugeriu. Talvez os links a seguir forneçam uma resposta. groups.google.com/a/cloudera.org/forum/#!topic/scm-users/… grokbase.com/t/cloudera/cdh-user/134r64jm5t/…
Emile
Eu estava adicionando hadoop-common-2.0.0-cdh4.3.0-sources.jar e hadoop-core-0.20.2.jar ao caminho da classe, removi primeiro e funcionou, não sei por quê.
Mahender Singh
1
Hmm ... Você poderia me falar sobre seu ambiente? Além disso, mostre-me a mensagem de exceção completa.
Tariq
Qual é o valor de modelPath? você já tentoufile:///path/to/dir
Chris White

Respostas:

174

Este é um caso típico de maven-assemblyfalha do plugin.

Por que isso aconteceu conosco

Diferentes JARs ( hadoop-commonsfor LocalFileSystem, hadoop-hdfsfor DistributedFileSystem) cada um contém um arquivo diferente chamado org.apache.hadoop.fs.FileSystemem seu META-INFO/servicesdiretório. Este arquivo lista os nomes de classe canônicos das implementações do sistema de arquivos que eles desejam declarar (isso é chamado de Interface de provedor de serviços implementada via java.util.ServiceLoader, consulte org.apache.hadoop.FileSystem#loadFileSystems).

Quando usamos maven-assembly-plugin, ele mescla todos os nossos JARs em um e todos META-INFO/services/org.apache.hadoop.fs.FileSystemsobrescrevem uns aos outros. Apenas um desses arquivos permanece (o último que foi adicionado). Nesse caso, a FileSystemlista de hadoop-commonssubstitui a lista de hadoop-hdfs, entãoDistributedFileSystem não foi mais declarada.

Como consertamos

Depois de carregar a configuração do Hadoop, mas antes de fazer qualquer coisa FileSystemrelacionada, chamamos isso de:

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

Atualização: a correção correta

Fui informado de krookedkingque existe uma forma baseada em configuração de fazer o maven-assemblyuso de uma versão mesclada de todas as FileSystemdeclarações de serviços, verifique sua resposta abaixo.

david_p
fonte
13
Este é o código equivalente necessário para fazer a mesma coisa no 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.
8
Na verdade, acabei de adicionar essa dependência http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.2.0do maven ao maven e o problema foi resolvido.
B.Mr.W.
6
Eu tentei adicionar hadoop-hdfs, hadoop-core, hadoop-common, hadoop-client, Aslo tentei adicionar hadoopConfig.set ("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName () ); hadoopConfig.set ("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName ()); mas não está funcionando, ao executar do eclipse está funcionando bem, mas ao executar do comando java -cp mostra o erro acima
Harish Pathak
1
Harish, o que você viu? O mesmo problema aqui, mas com intellij
ThommyH de
Apenas uma adição à resposta maravilhosa: se alguém estiver usando o JARS hadoop, mas executando o trabalho em um cluster não hadoop, "" "hadoopConfig.set (" fs.hdfs.impl ..... "" "" não trabalho. Nesse caso, recorreremos ao gerenciamento da construção do assembly. Por exemplo, no sbt, poderíamos fazer um mergeStrategy de concat ou mesmo filterDistinctLines
humano
62

Para aqueles que usam o plugin de sombra, seguindo o conselho de david_p, você pode mesclar os serviços no jar sombreado adicionando o ServicesResourceTransformer à configuração do 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>

Isso irá mesclar todos os serviços org.apache.hadoop.fs.FileSystem em um arquivo

krookedking
fonte
3
Eu gosto mais dessa solução. Corrija o problema na origem (a compilação) em vez de corrigi-lo com alterações de configuração após o fato.
Kevin Pauli,
1
Ótima resposta. Corrigido meu erro semelhante. Tentei com maven-assembly-plugin, bem como a combinação maven-jar-plugin / maven-dependency-plugin, mas não funcionou. Essa solução fez meu aplicativo Spark funcionar. Muito obrigado!
somnathchakrabarti
Ótima resposta! Muito obrigado!
andrea.lagala
Isso deve ser marcado como a resposta aceita. O ServicesResourceTransformer é necessário para quando os arquivos jar mapeiam interfaces para implementações usando um diretório META-INF / services. Mais informações podem ser encontradas aqui: maven.apache.org/plugins/maven-shade-plugin/examples/…
Mario
Excelente resposta.
Niranjan Subramanian
9

Para registro, isso ainda está acontecendo no hadoop 2.4.0. Tão frustrante...

Consegui seguir as instruções neste link: http://grokbase.com/t/cloudera/scm-users/1288xszz7r/no-filesystem-for-scheme-hdfs

Eu adicionei o seguinte ao meu core-site.xml e funcionou:

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

obrigado 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>
Andy
fonte
1
Só depois que eu li isso me fez perceber que o conf aqui foi a configuração Hadoop: brucebcampbell.wordpress.com/2014/12/11/...
Sal
8

Levei séculos para descobrir isso com o Spark 2.0.2, mas aqui vai minha parte:

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)

E as partes relevantes do meu build.sbt:

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

Espero que isso possa ajudar!

Mauro Arnoldi
fonte
5

Supondo que você esteja usando a distribuição mvn e cloudera do hadoop. Estou usando o cdh4.6 e adicionar essas dependências funcionou para mim. Acho que você deve verificar as versões das dependências hadoop e 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ão se esqueça de adicionar o repositório cloudera mvn.

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

Eu uso o assembly sbt para empacotar meu projeto. Eu também encontro esse problema. Minha solução está aqui. Passo 1: adicione META-INF mergestrategy em seu build.sbt

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

Passo 2: adicione hadoop-hdfs lib a build.sbt

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

Passo 3: sbt clean; montagem sbt

Espero que as informações acima possam ajudá-lo.

Haimei
fonte
15
Uma solução melhor pode ser fundir como: case PathList("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLinesIsto irá manter todos os sistemas de arquivos registrados
ravwojdyla
Obrigado em @ravwojdyla, solução muito legal. Você salvou meu cabelo. Para as almas perdidas descobrindo esta resposta para a faísca Apache. Adicione isso a build.sbt quando sbt-assembly funcionar corretamente.
Greedy Coder
A solução fornecida por @ravwojdyla é a única que funcionou para mim.
Sergey Kovalev
2
A solução dada por @ravwojdyla é ideal. Fiz uma configuração semelhante em build.sbt e usei: `` `assemblyMergeStrategy em 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

Presumo que você construa a amostra usando o maven.

Verifique o conteúdo do JAR que você está tentando executar. Especialmente META-INFO/servicesdiretório, arquivo org.apache.hadoop.fs.FileSystem. Deve haver uma lista de classes de implementação do sistema de arquivos. A linha de verificação org.apache.hadoop.hdfs.DistributedFileSystemestá presente na lista para HDFS e org.apache.hadoop.fs.LocalFileSystempara esquema de arquivo local.

Se for esse o caso, você deve substituir o recurso referido durante a construção.

Outra possibilidade é você simplesmente não ter hadoop-hdfs.jarem seu caminho de classe, mas isso tem baixa probabilidade. Normalmente, se você tiver hadoop-clientdependência correta , não é uma opção.

Roman Nikitchenko
fonte
HI Roman .. tenho o mesmo problema e o META-INFO / services / org.apache.hadoop.fs.FileSystem não tem linha hdfs.Tenho 2.0.0-mr1-cdh4.4.0 como única dependência. O que eu preciso fazer? Alguma documentação sobre isso? Usando Maven para construir
sethi
2

Outra causa possível (embora a questão dos OPs não sofra com isso) é se você criar uma instância de configuração que não carregue os padrões:

Configuration config = new Configuration(false);

Se você não carregar os padrões, não obterá as configurações padrão para coisas como as FileSystemimplementações, o que leva a erros idênticos como este ao tentar acessar o HDFS. Mudar para o construtor sem parâmetros de passagem truepara padrões de carregamento pode resolver isso.

Além disso, se você estiver adicionando locais de configuração personalizados (por exemplo, no sistema de arquivos) ao Configurationobjeto, tome cuidado com a sobrecarga addResource()usada. Por exemplo, se você usar addResource(String), o Hadoop pressupõe que a string é um recurso de caminho de classe; se você precisar especificar um arquivo local, tente o seguinte:

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

Levei algum tempo para descobrir a correção a partir de respostas dadas, devido à minha novidade. Isso é o que eu descobri, se alguém precisar de ajuda desde o início:

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)

Estou usando o Spark 2.1

E eu tenho essa parte no meu build.sbt

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

set fs.defaultFS funciona para mim! Hadoop-2.8.1

Asran Deng
fonte
1

Para SBT, use abaixo mergeStrategy em 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
fonte
0

Use este plugin

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

Se você estiver usando 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
fonte
0

Eu enfrentei o mesmo problema. Encontrei duas soluções: (1) Editar o arquivo jar manualmente:

Abra o arquivo jar com WinRar (ou ferramentas semelhantes). Acesse Meta-info> serviços e edite "org.apache.hadoop.fs.FileSystem" anexando:

org.apache.hadoop.fs.LocalFileSystem

(2) Alterando a ordem das minhas dependências como segue

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

Isso não está relacionado ao Flink, mas também encontrei esse problema no Flink.

Para quem usa o Flink, você precisa baixar o Hadoop pré-empacotado e colocá-lo dentro /opt/flink/lib.

David Magalhães
fonte
-1

Eu também me deparei com um problema semelhante. Adicionados core-site.xml e 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"));

Também editou conflitos de versão em pom.xml. (por exemplo, se a versão configurada do hadoop for 2.8.1, mas no arquivo pom.xml, as dependências têm a versão 2.7.1, então mude para 2.8.1) Execute a instalação do Maven novamente.

Isso resolveu o erro para mim.

Raxit Solanki
fonte