2019-01-10
概述
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程序版本不一致导致的。我这边就暂时不作深究了。。
+++