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 下安裝:
- Eclipse Photon Release (4.8.0)
- JDK 1.8
- 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的過程大致如下:
- 新建一個Java Project
- 貼上上面的原始碼
- 在HDFS叢集上將 ./hadoop/share/hadoop 目錄下相關的jar庫拷出來,新增到Project依賴庫中。
- 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程式版本不一致導致的。我這邊就暫時不作深究了。。