hadoop Brak systemu plików dla schematu: plik

97

Próbuję uruchomić prosty NaiveBayesClassiferprzy użyciu hadoop, otrzymując ten błąd

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)

Kod :

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

modelPathwskazuje NaiveBayes.binplik, a obiekt konfiguracyjny drukuje -Configuration: core-default.xml, core-site.xml

Myślę, że to z powodu słoików, jakieś pomysły?

Mahender Singh
źródło
Potrzebujemy więcej informacji ...
Tariq
2
Sam nie wiem, ale szybkie spojrzenie w Google sugeruje, że są pewne problemy związane z brakiem odwołań do słoików, jak sugerowałeś. Być może poniższe linki dadzą odpowiedź. groups.google.com/a/cloudera.org/forum/#!topic/scm-users/… grokbase.com/t/cloudera/cdh-user/134r64jm5t/…
Emile
Dodawałem hadoop-common-2.0.0-cdh4.3.0-sources.jar i hadoop-core-0.20.2.jar do ścieżki klas, najpierw usunąłem i zadziałało nie wiem dlaczego.
Mahender Singh
1
Hmm ... czy mógłbyś mi opowiedzieć o swoim środowisku? Pokaż mi również całą wiadomość o wyjątku.
Tariq
Jaka jest wartość modelPath? próbowałeśfile:///path/to/dir
Chris White

Odpowiedzi:

175

Jest to typowy przypadek maven-assemblyzepsucia wtyczki.

Dlaczego to nam się przydarzyło

Każdy z różnych plików JAR ( hadoop-commonsfor LocalFileSystem, hadoop-hdfsfor DistributedFileSystem) zawiera inny plik o nazwie org.apache.hadoop.fs.FileSystemw swoim META-INFO/serviceskatalogu. Ten plik zawiera kanoniczne nazwy klas implementacji systemu plików, które chcą zadeklarować (nazywa się to interfejsem dostawcy usług zaimplementowanym za pośrednictwem java.util.ServiceLoader, patrzorg.apache.hadoop.FileSystem#loadFileSystems ).

Kiedy używamy maven-assembly-plugin, łączy wszystkie nasze pliki JAR w jeden i wszystkie META-INFO/services/org.apache.hadoop.fs.FileSystemnadpisują się nawzajem. Pozostał tylko jeden z tych plików (ostatni dodany). W tym przypadku FileSystemlista z hadoop-commonsnadpisuje listę z hadoop-hdfs, więc DistributedFileSystemnie była już deklarowana.

Jak to naprawiliśmy

Po załadowaniu konfiguracji Hadoop, ale tuż przed zrobieniem czegokolwiek związanego FileSystem, nazywamy to:

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

Aktualizacja: poprawna poprawka

Zwróciło mi uwagę, krookedkingże istnieje sposób oparty na konfiguracji, aby maven-assemblyużyć połączonej wersji wszystkich FileSystemdeklaracji usług, sprawdź jego odpowiedź poniżej.

david_p
źródło
13
Oto równoważny kod wymagany do zrobienia tego samego w Sparku: 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
Właściwie właśnie dodałem tę zależność http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.2.0mavena do mavena i rozwiązałem problem.
B.Mr.W.
6
Próbowałem dodać hadoop-hdfs, hadoop-core, hadoop-common, hadoop-client, Aslo próbowałem dodać hadoopConfig.set ("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName () ); hadoopConfig.set ("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName ()); ale nie działa, podczas uruchamiania z zaćmienia działa dobrze, ale podczas uruchamiania z polecenia java -cp pokazuje powyższy błąd
Harish Pathak
1
Harish, co widziałeś? Ten sam problem, ale z intellij
ThommyH
To tylko dodatek do cudownej odpowiedzi: jeśli ktoś używa hadoop JARS, ale działa w klastrze bez hadoop, "" "hadoopConfig.set (" fs.hdfs.impl ..... "" "" nie będzie W takim przypadku wrócimy do zarządzania budową zestawu, np. w sbt możemy wykonać mergeStrategy of concat lub nawet filterDistinctLines
human
62

Dla tych, którzy używają wtyczki cieniowania, zgodnie z radą david_p, możesz scalić usługi w cieniowanym jar, dodając ServicesResourceTransformer do konfiguracji wtyczki:

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

Spowoduje to scalenie wszystkich usług org.apache.hadoop.fs.FileSystem w jeden plik

krzywo
źródło
3
Najbardziej podoba mi się to rozwiązanie. Napraw problem w źródle (kompilacji) zamiast łatać go zmianami konfiguracyjnymi po fakcie.
Kevin Pauli
1
Świetna odpowiedź. Naprawiono mój podobny błąd. Próbowano z połączeniem maven-assembly-plugin oraz maven-jar-plugin / maven-dependency-plugin, ale nie działało. To rozwiązanie sprawiło, że moja aplikacja Spark działała. Wielkie dzięki!
somnathchakrabarti
Świetna odpowiedź! Wielkie dzięki!
andrea.lagala
Powinno to zostać oznaczone jako zaakceptowana odpowiedź. ServicesResourceTransformer jest niezbędny, gdy pliki jar mapują interfejsy do implementacji przy użyciu katalogu META-INF / services. Więcej informacji można znaleźć tutaj: maven.apache.org/plugins/maven-shade-plugin/examples/…
Mario
Doskonała odpowiedź.
Niranjan Subramanian
9

Dla przypomnienia, to nadal się dzieje w Hadoop 2.4.0. Bardzo frustrujące...

Udało mi się postępować zgodnie z instrukcjami w tym linku: http://grokbase.com/t/cloudera/scm-users/1288xszz7r/no-filesystem-for-scheme-hdfs

Dodałem następujący plik do mojego core-site.xml i zadziałało:

<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>
Achajasz
źródło
8

dzięki 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);

lub

<property>
 <name>fs.hdfs.impl</name>
 <value>org.apache.hadoop.hdfs.DistributedFileSystem</value>
</property>
Andy
źródło
1
Dopiero po przeczytaniu to zdałem sobie sprawę, że conf tutaj był Konfiguracja Hadoop: brucebcampbell.wordpress.com/2014/12/11/...
Sal
8

Wieki zajęło mi rozgryzienie tego w Spark 2.0.2, ale oto moja część:

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)

I odpowiednie części mojego build.sbt:

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

Mam nadzieję, że to pomoże!

Mauro Arnoldi
źródło
5

Zakładając, że używasz dystrybucji hadoop mvn i cloudera. Używam cdh4.6 i dodanie tych zależności zadziałało. Myślę, że powinieneś sprawdzić wersje zależności hadoop i 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>

nie zapomnij dodać repozytorium cloudera mvn.

<repository>
        <id>cloudera</id>
        <url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
husnu
źródło
4

Używam zestawu SBT do spakowania mojego projektu. Ja też spotykam się z tym problemem. Moje rozwiązanie jest tutaj. Krok 1: dodaj strategię łączenia META-INF w pliku build.sbt

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

Krok 2: dodaj bibliotekę hadoop-hdfs do build.sbt

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

Step3: sbt clean; montaż sbt

Mam nadzieję, że powyższe informacje mogą ci pomóc.

Haimei
źródło
15
Lepszym rozwiązaniem może być scalenie na przykład: case PathList("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLinesTo zachowa wszystkie zarejestrowane systemy plików
ravwojdyla
Dzięki @ravwojdyla, całkiem zgrabne rozwiązanie. Uratowałeś mi włosy. Dla zagubionych dusz odkrywających tę odpowiedź na iskrę Apache. Dodaj to do build.sbt, gdy sbt-assembly, działa poprawnie.
Greedy Coder
Rozwiązanie dostarczone przez @ravwojdyla jest jedynym, które działało dla mnie.
Sergey Kovalev
2
Rozwiązanie podane przez @ravwojdyla jest idealne. Zrobiłem podobną konfigurację w build.sbt i użyłem: `` 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} ``
człowiek
2

Zakładam, że tworzysz sample używając Mavena.

Sprawdź zawartość pliku JAR, który próbujesz uruchomić. Szczególnie META-INFO/serviceskatalog, plik org.apache.hadoop.fs.FileSystem. Powinna być lista klas implementacji systemu plików. Linia kontrolna org.apache.hadoop.hdfs.DistributedFileSystemjest obecna na liście dla HDFS i org.apache.hadoop.fs.LocalFileSystemlokalnego schematu plików.

W takim przypadku musisz przesłonić przywołany zasób podczas kompilacji.

Inną możliwością jest to, że po prostu nie masz hadoop-hdfs.jarw swojej ścieżce klas, ale jest to małe prawdopodobieństwo. Zwykle, jeśli masz poprawną hadoop-clientzależność, nie ma takiej opcji.

Roman Nikitchenko
źródło
HI Roman ..i mają ten sam problem, a META-INFO / services / org.apache.hadoop.fs.FileSystem nie ma linii hdfs. Mam 2.0.0-mr1-cdh4.4.0 jako jedyną zależność. Co muszę zrobić? Jakaś dokumentacja na ten temat? Używanie Mavena do budowania
sethi
2

Inną możliwą przyczyną (chociaż samo pytanie OPs nie cierpi z tego powodu) jest utworzenie instancji konfiguracji, która nie ładuje ustawień domyślnych:

Configuration config = new Configuration(false);

Jeśli nie załadujesz ustawień domyślnych, nie uzyskasz ustawień domyślnych dla rzeczy takich jak FileSystemimplementacje, które prowadzą do identycznych błędów, takich jak ten, podczas próby uzyskania dostępu do HDFS. Przełączenie do konstruktora bez parametrów, który przekazuje truewartości domyślne w celu załadowania, może rozwiązać ten problem.

Dodatkowo, jeśli dodajesz niestandardowe lokalizacje konfiguracji (np. W systemie plików) do Configurationobiektu, uważaj na to, jakiego przeciążenia addResource()używasz. Na przykład, jeśli używasz, addResource(String)Hadoop zakłada, że ​​ciąg jest zasobem ścieżki klasy, jeśli chcesz określić plik lokalny, spróbuj wykonać następujące czynności:

File configFile = new File("example/config.xml");
config.addResource(new Path("file://" + configFile.getAbsolutePath()));
RobV
źródło
1

Zajęło mi trochę czasu, aby znaleźć rozwiązanie na podstawie udzielonych odpowiedzi, ze względu na moją nowość. Oto co wymyśliłem, jeśli ktoś potrzebuje pomocy od samego początku:

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)

Używam Spark 2.1

I mam tę część w moim build.sbt

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

zestaw fs.defaultFS działa dla mnie! Hadoop-2.8.1

Asran Deng
źródło
1

Dla SBT użyj poniżej mergeStrategy w 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
źródło
0

Użyj tej wtyczki

<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
źródło
0

Jeśli używasz 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
źródło
0

Miałem ten sam problem. Znalazłem dwa rozwiązania: (1) Ręczna edycja pliku jar:

Otwórz plik jar za pomocą WinRar (lub podobnych narzędzi). Przejdź do Meta-info> services i edytuj „org.apache.hadoop.fs.FileSystem”, dodając:

org.apache.hadoop.fs.LocalFileSystem

(2) Zmiana kolejności moich zależności w następujący sposób

<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
źródło
0

Nie jest to związane z Flink, ale znalazłem ten problem również w Flink.

W przypadku osób korzystających z Flink należy pobrać wstępnie dołączony Hadoop i umieścić go w środku /opt/flink/lib.

David Magalhães
źródło
-1

Trafiłem też na podobny problem. Dodano core-site.xml i hdfs-site.xml jako zasoby conf (obiekt)

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

Również edytowane konflikty wersji w pom.xml. (np. jeśli skonfigurowana wersja hadoop to 2.8.1, ale w pliku pom.xml, zależności mają wersję 2.7.1, zmień ją na 2.8.1) Uruchom ponownie instalację Mavena.

Ten błąd rozwiązał za mnie.

Raxit Solanki
źródło