Я пытаюсь запустить простой 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
Я думаю, что это из-за банок, любых идей?
Ответ 1
Это типичный случай, когда плагин maven-assembly
ломает вещи.
Почему это случилось с нами
Различные JAR файлы (hadoop-commons
для LocalFileSystem
, hadoop-hdfs
для DistributedFileSystem
) содержат в своем каталоге META-INFO/services
отдельный файл с именем org.apache.hadoop.fs.FileSystem
. В этом файле перечислены канонические имена классов реализаций файловой системы, которые они хотят объявить (это называется интерфейсом поставщика услуг, реализованным через java.util.ServiceLoader
, см. org.apache.hadoop.FileSystem
строка 2622).
Когда мы используем maven-assembly-plugin
, он объединяет все наши JAR файлы в один, и все META-INFO/services/org.apache.hadoop.fs.FileSystem
перезаписывают друг друга. Остается только один из этих файлов (последний, который был добавлен). В этом случае список FileSystem
из hadoop-commons
перезаписывает список из hadoop-hdfs
, поэтому DistributedFileSystem
больше не объявляется.
Как мы это исправили
После загрузки конфигурации Hadoop, но перед тем, как что-либо делать FileSystem
-related, мы вызываем это:
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
, посмотрите его ответ ниже.
Ответ 2
Для тех, кто использует плагин shadow, следуя советам david_p, вы можете объединить службы в затененной банке, добавив ServiceResourceTransformer в конфигурацию плагина:
<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 в одном файле
Ответ 3
Для записи это все еще происходит в hadoop 2.4.0. Так расстраивает...
Мне удалось выполнить инструкции по этой ссылке: http://grokbase.com/t/cloudera/scm-users/1288xszz7r/no-filesystem-for-scheme-hdfs
Я добавил следующее к моему основному сайту .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>
Ответ 4
Мне приходилось разбираться с 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
спасибо 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>
Ответ 6
Для maven просто добавьте зависимость maven для hadoop-hdfs (см. Ссылку ниже), решит проблему.
http://mvnrepository.com/artifact/org.apache.hadoop/hadoop-hdfs/2.7.1
Ответ 7
Предполагая, что вы используете 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>
Ответ 8
Я использую сборку sbt для упаковки моего проекта. Я также встречаю эту проблему. Мое решение здесь.
Шаг 1: добавьте META-INF mergestrategy в свой build.sbt
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
case PathList("META-INF", ps @ _*) => MergeStrategy.first
Шаг 2: добавьте hasoop-hdfs lib в build.sbt
"org.apache.hadoop" % "hadoop-hdfs" % "2.4.0"
Шаг 3: sbt clean; сборка sbt
Надеемся, что приведенная выше информация поможет вам.
Ответ 9
Я предполагаю, что вы создаете образец с помощью 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
, это не вариант.
Ответ 10
Другая возможная причина (хотя вопрос OPs сам по себе не страдает) заключается в том, что вы создаете экземпляр конфигурации, который не загружает значения по умолчанию:
Configuration config = new Configuration(false);
Если вы не загрузите значения по умолчанию, вы не получите настройки по умолчанию для таких вещей, как реализация FileSystem
, что приводит к идентичным ошибкам, подобным этому при попытке доступа к HDFS. Переход на конструктор без параметров, проходящий в true
для загрузки значений по умолчанию, может решить эту проблему.
Кроме того, если вы добавляете настраиваемые местоположения конфигурации (например, в файловую систему) к объекту Configuration
, будьте осторожны с перегрузкой addResource()
, которую вы используете. Например, если вы используете addResource(String)
, то Hadoop предполагает, что строка является ресурсом пути класса, если вам нужно указать локальный файл, попробуйте следующее:
File configFile = new File("example/config.xml");
config.addResource(new Path("file://" + configFile.getAbsolutePath()));
Ответ 11
Мне потребовалось некоторое время, чтобы выяснить, исправить ли из ответов, из-за моей newbieness. Это то, с чем я столкнулся, если кто-то еще нуждается в помощи с самого начала:
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
}
Ответ 12
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);
set fs.defaultFS работает для меня! Hadoop-2.8.1
Ответ 13
Для использования 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)
}
}
Ответ 14
Если вы используете 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
)
Ответ 15
Для тех, кто использует Spark Java:
SparkSession session = SparkSession.builder().master("local[*]").getOrCreate();
session.sparkContext().hadoopConfiguration().set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
session.sparkContext().hadoopConfiguration().set("fs.file.impl", "org.apache.hadoop.fs.LocalFileSystem");'''
Ответ 16
Я столкнулся с той же проблемой. Я нашел два решения:
(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>
Ответ 17
Используйте этот плагин
<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>
Ответ 18
Я также столкнулся с подобной проблемой.
Добавлены 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 еще раз.
Эта разрешенная ошибка для меня.