1. 程式人生 > >Eclipse maven hadoop -- java.io.IOException: No FileSystem for scheme: hdfs

Eclipse maven hadoop -- java.io.IOException: No FileSystem for scheme: hdfs

2019-01-10

 

概述

  今天在Windows系統下新安裝了Eclipse和maven的環境,想利用Maven構建一個Hadoop程式的,結果卻發現程式執行時一直報 “No FileSystem for scheme: hdfs” 的異常。網友貼出的解決方案在我這都不適用。經過數小時痛苦的折磨以後才終於找到我這種情況的原因:Maven自動下載的 hadoop-hdfs-2.7.7.jar 庫檔案不正確!!!

 

環境

HDFS搭建在一組ubuntu server叢集上,系統正常執行。 Hadoop 2.7.7

Windows 10 下安裝:

  1. Eclipse  Photon Release (4.8.0)
  2. JDK 1.8
  3. Maven 3.6.0

Eclipse上所使用的主要原始碼如下:

 1     void access() {
 2         Configuration conf = new Configuration();
 3         conf.set("fs.defaultFS", "hdfs://usmaster:8020");
 4         try {
 5             FileSystem fs = FileSystem.get(conf); //執行到該行時報異常。
6 System.out.println(fs.getHomeDirectory().toUri().toString()); 7 System.out.println("read end!"); 8 } catch (Exception e) { 9 e.printStackTrace(); 10 } 11 }

異常棧資訊如下:

java.io.IOException: No FileSystem for scheme: hdfs
    at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:
2658) at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2665) at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:93) at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2701) at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2683) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:372) at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:171) ...

 

解決過程

  遇到這個問題,首先思考下異常原因:No FileSystem for scheme: hdfs 。似乎是不能識別hdfs協議!那首先來檢查一下HDFS系統的執行狀況。經檢查,我的HDFS叢集執行正常。WEB UI正常開啟,也可以通過Shell命令正常地與HDFS互動。排除掉HDFS系統的原因。

  其次檢查我的原始碼,為了糾錯將原始碼縮減到最減化的地步,如上面貼出來的程式碼所示。根據程式碼來看,也可以排除掉我寫的程式碼有錯誤的原因。

  然後再檢查Maven的pom配置資訊。我的pom.xml全文如下所示:

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3   <modelVersion>4.0.0</modelVersion>
 4 
 5   <groupId>com.chorm</groupId>
 6   <artifactId>HelloWorld</artifactId>
 7   <version>0.0.1-SNAPSHOT</version>
 8   <packaging>jar</packaging>
 9 
10   <name>HDFS</name>
11   <url>http://maven.apache.org</url>
12 
13   <properties>
14     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15     <hadoop.version>2.7.7</hadoop.version>
16   </properties>
17 
18   <dependencies>
19     <dependency>
20       <groupId>junit</groupId>
21       <artifactId>junit</artifactId>
22       <version>3.8.1</version>
23       <scope>test</scope>
24     </dependency>
25     
26     <dependency>
27       <groupId>org.apache.hadoop</groupId>
28       <artifactId>hadoop-client</artifactId>
29       <version>${hadoop.version}</version>
30     </dependency>
31     
32   </dependencies>
33 </project>

  同時檢查了專案的Maven Dependencies,該有的jar包都有。似乎也和Maven依賴沒關係。

  那接下來再檢查JRE,似乎也沒發現問題。。。

  好嘛,檢查一圈下來哪哪都沒問題,那它怎麼就是報錯???

 

  現在只剩百度了。。。經過一番搜尋,網上雖然也有不少報相同異常的情況,但是按照他們的方案都沒能解決我的問題。還得繼續靠自己來分析。。。

 

那我就不用Maven來構建程式。我直接建立一個Java Project,看看有沒有可能是我下載的Maven程式有問題。建立Java Project的過程大致如下:

  1. 新建一個Java Project
  2. 貼上上面的原始碼
  3. 在HDFS叢集上將 ./hadoop/share/hadoop 目錄下相關的jar庫拷出來,新增到Project依賴庫中。
  4. run it...

 

正常執行。。。

這似乎真和Maven脫不了干係。

 

那隻能除錯程式了。。。。

首先定位到丟擲這個異常的程式碼:

at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2658)

圖1 

  由上圖來看,拋異常是因為claszz變數在第2652行第2655行都沒能得到物件引起的(找不到物件的變數真的是可怕)。第2652行是要從Configuration物件中讀取配置資訊的,就是從core-default.xml或core-site.xml中讀取配置資訊。這個資訊我這邊並沒有指定,所以它肯定是返回一個NULL的。那我們在第2654行打一個斷點,來除錯一下看怎麼回事。

圖2

  單步跳過第2655行以後看一下這個SERVICE_FILE_SYSTEMS變數。

圖3

  似乎這個物件裡真的沒有key值能匹配“hdfs”的物件值啊。這就有點奇怪了。那再除錯一下前面自己建的那個“Java Project”,在同樣位置打斷點來檢視這個變數值。

圖4

  神奇了。。。為什麼用maven構建的程式會導致這個SERVICE_FILE_SYSTEMS變數裡沒有“hdfs”的物件?去看看這個SERVICE_FILE_SYSTEMS是在哪裡賦值的。

圖5

  查了原始碼,這個SERVICE_FILE_SYSTEMS只在這一處地方有賦值操作。其值來自於ServiceLoader.load(FileSystem.class)。我不瞭解這個ServiceLoader.load()方法是幹什麼的,不過似乎和hadoop的FileSystem有關係,經查詢這個FileSystem來自於hadoop-common-2.7.7.jar庫。這個FileSystem類在Maven構建的程式中的依賴庫中能找到,在Java Project中手動新增的依賴庫中也能找到。

圖6

  再去查一下上圖4中那個與“hdfs”有關的DistriubtedFileSystem的類。卻發現只能在自己建立的Java Project中找到它位於hadoop-hdfs-2.7.7.jar中,在Maven構建的程式中沒有!!難道是maven自動下載的hadoop-hdfs-2.7.7.jar 庫有問題?開啟來看一下。

圖7

  神奇有沒有,maven自動下載的庫中也有這個class。但是為什麼似乎Eclipse就是識別不到它??

  再對比一下這兩個hadoop-hdfs-2.7.7.jar的檔案屬性資訊。

圖8

  檔案大小顯然不一樣,這兩個庫有差異啊!

  那將我手動從HDFS中匯出來的hadoop-hdfs-2.7.7.jar替換掉我Maven自動下載的那個hadoop-hdfs-2.7.7.jar來試試。

圖9

  執行程式。。

圖10

  問題解決!!!!

 

  不過我至今搞不懂為什麼maven自動下載的那個hadoop-hdfs-2.7.7.jar庫會不行。。也搞不懂這兩個庫之間的差異是怎麼回事。

  不過我這邊安裝的HDFS是直接在Hadoop的官網上下載的2.7.7版本。我不知道Maven幫我下載的庫是不是什麼CDH版本的。也許真的是依賴庫檔案來源的Hadoop程式版本不一致導致的。我這邊就暫時不作深究了。。