Hadoopを使用して簡単なNaiveBayesClassifer
を実行しようとしていますが、このエラーが発生します
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
ジャーのせいだと思いますか?
これは、maven-Assembly
プラグインが問題を引き起こす典型的なケースです。
さまざまなJAR(hadoop-commons
for LocalFileSystem
、hadoop-hdfs
for DistributedFileSystem
)にはそれぞれ、org.Apache.hadoop.fs.FileSystem
ディレクトリにMETA-INFO/services
という異なるファイルが含まれています。このファイルは、宣言したいファイルシステム実装の正規のクラス名をリストします(これは、Java.util.ServiceLoader
を介して実装されるサービスプロバイダーインターフェイスと呼ばれます。org.Apache.hadoop.FileSystem
行2622 を参照)。
maven-Assembly-plugin
を使用すると、すべてのJARが1つにマージされ、すべてのMETA-INFO/services/org.Apache.hadoop.fs.FileSystem
が互いに上書きします。これらのファイルの1つだけが残ります(最後に追加されたファイル)。この場合、hadoop-commons
のFileSystem
リストは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
サービス宣言のマージされたバージョンを使用するようにする構成ベースの方法があることに気づきました。次のプラグインをpom.xml
ファイルに追加します。
<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>
シェードプラグインを使用している場合は、david_pのアドバイスに従って、ServicesResourceTransformerをプラグイン構成に追加することで、シェーディングされたjarのサービスをマージできます。
<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サービスが1つのファイルにマージされます
記録のために、これはまだ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>
ありがとう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>
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"
これが役立つことを願っています!
Mavenの場合、hadoop-hdfsのMaven依存関係を追加するだけで(以下のリンクを参照)、問題が解決します。
http://mvnrepository.com/artifact/org.Apache.hadoop/hadoop-hdfs/2.7.1
Sbt Assemblyを使用してプロジェクトをパッケージ化します。私もこの問題に直面しています。私の解決策はこちらです。ステップ1:build.sbtにMETA-INF mergestrategyを追加
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
case PathList("META-INF", ps @ _*) => MergeStrategy.first
ステップ2:hadoop-hdfs libをbuild.sbtに追加します
"org.Apache.hadoop" % "hadoop-hdfs" % "2.4.0"
ステップ3:sbt clean; sbtアセンブリ
上記の情報がお役に立てば幸いです。
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>
別の考えられる原因(OPの質問自体はこの問題の影響を受けませんが)は、デフォルトをロードしない設定インスタンスを作成した場合です:
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()));
Mavenを使用してサンプルをビルドすると仮定します。
実行しようとしているJARの内容を確認してください。特にMETA-INFO/services
ディレクトリ、ファイルorg.Apache.hadoop.fs.FileSystem
。 filsystem実装クラスのリストがあるはずです。行org.Apache.hadoop.hdfs.DistributedFileSystem
がHDFSのリストにあり、org.Apache.hadoop.fs.LocalFileSystem
がローカルファイルスキームにあることを確認します。
この場合、ビルド中に参照されたリソースをオーバーライドする必要があります。
他の可能性としては、クラスパスにhadoop-hdfs.jar
がないだけですが、これは低い確率です。通常、正しいhadoop-client
依存関係がある場合、これはオプションではありません。
SBTの場合、build.sbtのmergeStrategyの下で使用します
mergeStrategy in Assembly <<= (mergeStrategy in Assembly) { (old) => {
case PathList("META-INF", "services", "org.Apache.hadoop.fs.FileSystem") => MergeStrategy.filterDistinctLines
case s => old(s)
}
}
私の初心者のため、与えられた答えから修正を見つけるのに時間がかかりました。他の誰かが最初から助けを必要とする場合、これは私が思いついたものです:
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
}
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nameNode:9000");
FileSystem fs = FileSystem.get(conf);
set fs.defaultFSは私のために動作します! Hadoop-2.8.1
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
)