hadoop Нет файловой системы для схемы: файл

97

Я пытаюсь запустить простой NaiveBayesClassiferс помощью hadoop, получаю эту ошибку

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

Думаю, это из-за банок, есть идеи?

Махендер Сингх
источник
Нужна дополнительная информация ...
Тарик
2
Сам не знаю, но беглый взгляд на Google показывает, что есть некоторые проблемы с банками, на которые не ссылаются, как вы предложили. Возможно, следующие ссылки дадут ответ. groups.google.com/a/cloudera.org/forum/#!topic/scm-users/… grokbase.com/t/cloudera/cdh-user/134r64jm5t/…
Эмиль
Я добавлял hadoop-common-2.0.0-cdh4.3.0-sources.jar и hadoop-core-0.20.2.jar в путь к классу, сначала удалил, и это сработало, не знаю почему.
Махендер Сингх
1
Хм .. Не могли бы вы рассказать мне о вашем окружении? Кроме того, покажите мне полное сообщение об исключении.
Tariq
В чем ценность modelPath? Вы пробовалиfile:///path/to/dir
Крис Уайт

Ответы:

175

Это типичный случай maven-assemblyполомки плагина.

Почему это случилось с нами

Каждый из разных JAR ( hadoop-commonsfor LocalFileSystem, hadoop-hdfsfor DistributedFileSystem) содержит разные файлы, вызываемые org.apache.hadoop.fs.FileSystemв их META-INFO/servicesкаталогах. В этом файле перечислены канонические имена классов реализаций файловой системы, которые они хотят объявить (это называется интерфейсом поставщика услуг, реализованным через java.util.ServiceLoader, см. org.apache.hadoop.FileSystem#loadFileSystems).

Когда мы используем maven-assembly-plugin, он объединяет все наши JAR в один, и все META-INFO/services/org.apache.hadoop.fs.FileSystemперезаписывают друг друга. Остается только один из этих файлов (последний добавленный). В этом случае FileSystemсписок из hadoop-commonsзаменяет список из 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объявлений сервисов, посмотрите его ответ ниже.

david_p
источник
13
Вот эквивалентный код, необходимый для того же в 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)
Филип О.
8
На самом деле, я просто добавил эту зависимость http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.2.0maven к maven, и проблема решена.
B.Mr.W.
6
Я пробовал добавить hadoop-hdfs, hadoop-core, hadoop-common, hadoop-client, Асло попытался добавить hadoopConfig.set ("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName () ); hadoopConfig.set ("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName ()); но не работает, при запуске из eclipse он работает нормально, но при запуске из команды java -cp показывает ошибку выше
Хариш Патхак,
1
Хариш, что ты видел? Та же проблема здесь, но с intellij
ThommyH
Просто дополнение к замечательному ответу: если кто-то использует HADoop JARS, но выполняет задание в кластере, отличном от HADoop, "" "hadoopConfig.set (" fs.hdfs.impl ..... "" "" не будет В этом случае мы вернемся к управлению сборкой сборки. например, в sbt мы могли бы сделать mergeStrategy of concat или даже filterDistinctLines
human
62

Для тех, кто использует плагин тени, следуя совету david_p, вы можете объединить службы в затененной банке, добавив ServicesResourceTransformer в конфигурацию плагина:

  <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 в один файл.

Krookedking
источник
3
Мне больше всего нравится это решение. Исправьте проблему в источнике (сборке), а не исправляйте ее изменениями конфигурации постфактум.
Кевин Паули
1
Отличный ответ. Исправлена ​​моя аналогичная ошибка. Пробовал использовать maven-assembly-plugin, а также комбинацию maven-jar-plugin / maven-dependency-plugin, но не сработало. Это решение заставило мое приложение Spark работать. Большое спасибо!
somnathchakrabarti
Отличный ответ! Большое спасибо!
andrea.lagala
Это должно быть отмечено как принятый ответ. ServicesResourceTransformer необходим, когда файлы jar сопоставляют интерфейсы с реализациями с помощью каталога META-INF / services. Дополнительную информацию можно найти здесь: maven.apache.org/plugins/maven-shade-plugin/examples/…
Марио
Отличный ответ.
Ниранджан Субраманиан
9

Для справки, это все еще происходит в 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>
Ахайя
источник
8

спасибо 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>
Энди
источник
1
Только после того, как я прочитал это сделал я понимаю , что конф здесь была конфигурация Hadoop: brucebcampbell.wordpress.com/2014/12/11/...
Sal
8

Мне потребовалось много времени, чтобы понять это с помощью 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"

Надеюсь, это поможет!

Мауро Арнольди
источник
5

Предполагая, что вы используете mvn и cloudera для распространения hadoop. Я использую 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>
Husnu
источник
4

Я использую сборку sbt для упаковки своего проекта. Тоже встречаюсь с этой проблемой. Мое решение здесь. Шаг 1: добавьте стратегию слияния META-INF в свой build.sbt

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

Шаг 2: добавьте библиотеку hadoop-hdfs в build.sbt

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

Шаг 3: sbt clean; sbt сборка

Надеюсь, что приведенная выше информация поможет вам.

Haimei
источник
15
Лучшим решением может быть слияние, например: case PathList("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLinesЭто сохранит все зарегистрированные файловые системы
ravwojdyla
Спасибо @ravwojdyla, довольно интересное решение. Ты спас мои волосы. Для заблудших душ, открывших этот ответ для Apache Spark. Добавьте это в build.sbt, когда sbt-assembly работает правильно.
Greedy Coder
Решение, предоставленное @ravwojdyla, - единственное, что сработало для меня.
Сергей Ковалев
2
Решение, данное @ravwojdyla, идеально. Я сделал аналогичную настройку в build.sbt и использовал: `` assemblyMergeStrategy в сборке: = {case PathList ("META-INF", "MANIFEST.MF") => MergeStrategy.discard case PathList ("META-INF", "services", "org.apache.hadoop.fs.FileSystem") => MergeStrategy.concat case _ => MergeStrategy.first} ``
человек
2

Я предполагаю, что вы создаете образец с помощью maven.

Проверьте содержимое JAR, который вы пытаетесь запустить. Особенно META-INFO/servicesкаталог, файл org.apache.hadoop.fs.FileSystem. Должен быть список классов реализации файловой системы. Контрольная строка org.apache.hadoop.hdfs.DistributedFileSystemприсутствует в списке для HDFS и org.apache.hadoop.fs.LocalFileSystemдля локальной файловой схемы.

В этом случае вам необходимо переопределить указанный ресурс во время сборки.

Другая возможность - у вас просто нет hadoop-hdfs.jarв вашем пути к классам, но это имеет низкую вероятность. Обычно, если у вас правильная hadoop-clientзависимость, это не вариант.

Роман Никитченко
источник
Привет, Роман .. у меня такая же проблема, и у META-INFO / services / org.apache.hadoop.fs.FileSystem нет строки hdfs. У меня есть только 2.0.0-mr1-cdh4.4.0 в качестве единственной зависимости. Что мне нужно сделать? Есть документация по этому поводу? Использование Maven для сборки
сетхи
2

Другая возможная причина (хотя вопрос OPs сам по себе не страдает от этого) заключается в том, что вы создаете экземпляр конфигурации, который не загружает значения по умолчанию:

Configuration config = new Configuration(false);

Если вы не загрузите значения по умолчанию, вы не получите настройки по умолчанию для таких вещей, как FileSystemреализации, что приведет к таким же ошибкам, как эта, при попытке доступа к HDFS. Переключение на конструктор без параметров для перехода trueк загрузке значений по умолчанию может решить эту проблему.

Кроме того, если вы добавляете в Configurationобъект пользовательские конфигурации (например, в файловой системе), будьте осторожны с тем, какую перегрузку addResource()вы используете. Например, если вы используете addResource(String)then, Hadoop предполагает, что строка является ресурсом пути к классу, если вам нужно указать локальный файл, попробуйте следующее:

File configFile = new File("example/config.xml");
config.addResource(new Path("file://" + configFile.getAbsolutePath()));
RobV
источник
1

Мне потребовалось некоторое время, чтобы выяснить, как исправить полученные ответы из-за моей новизны. Вот что я придумал, если кому-то еще нужна помощь с самого начала:

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
}
Акавалл
источник
1
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);

set fs.defaultFS у меня работает! Hadoop-2.8.1

Асран Денг
источник
1

Для SBT используйте ниже mergeStrategy в 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

Используйте этот плагин

<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>
Хариш Патхак
источник
0

Если вы используете 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

Я столкнулся с той же проблемой. Я нашел два решения: (1) Редактирование файла jar вручную:

Откройте файл jar с помощью WinRar (или аналогичных инструментов). Перейдите в Meta-info> services и отредактируйте org.apache.hadoop.fs.FileSystem, добавив:

org.apache.hadoop.fs.LocalFileSystem

(2) Изменение порядка моих зависимостей следующим образом

<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>
Мохаммад-Али
источник
0

Это не связано с Flink, но я также обнаружил эту проблему во Flink.

Для людей, использующих Flink, вам необходимо загрузить предварительно собранный Hadoop и поместить его внутрь /opt/flink/lib.

Давид Магальяйнс
источник
-1

Я тоже столкнулся с подобной проблемой. Добавлены core-site.xml и hdfs-site.xml в качестве ресурсов conf (object)

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

Также редактировал конфликты версий в pom.xml. (например, если настроенная версия hadoop - 2.8.1, но в файле pom.xml, у зависимостей есть версия 2.7.1, затем измените ее на 2.8.1) Снова запустите установку Maven.

Это решило ошибку для меня.

Раксит Соланки
источник