`

Java程序中不通过hadoop jar的方式访问hdfs

 
阅读更多

 

转自http://brandnewuser.iteye.com/blog/2208709

 

 

 
一般情况下,我们使用Java访问hadoop distributed file system(hdfs)使用hadoop的相应api,添加以下的pom.xml依赖(这里以hadoop2.2.0版本为例):
 
Xml代码  收藏代码
  1. <dependency>  
  2.     <groupId>org.apache.hadoop</groupId>  
  3.     <artifactId>hadoop-common</artifactId>  
  4.     <version>2.2.0</version>  
  5. </dependency>  
  6. <dependency>  
  7.     <groupId>org.apache.hadoop</groupId>  
  8.     <artifactId>hadoop-mapreduce-client-core</artifactId>  
  9.     <version>2.2.0</version>  
  10. </dependency>  
  
 
在其中使用FileSystem就可以访问hdfs:
 
Java代码  收藏代码
  1. FileSystem fileSystem = null;  
  2. try {  
  3.     Configuration conf = new Configuration();  
  4.     fileSystem = FileSystem.get(conf);  
  5.     BufferedReader bufferedReader =  = new BufferedReader(new InputStreamReader(fsInputStream));  
 
 
但是需要注意的一点就是,只能在配置了hadoop环境的服务器上,通过hadoop jar的方式启动,hadoop jar的方式启动实际上调用的是org.apache.hadoop.util。RunJar作为入口。
 
RunJar会自动将此环境中的hadoop classpath设置,并初始化hadoop的环境变量等信息。
 
但是这种方式只能够写一个shell脚本来实现调用,其中使用hadoop jar的方式来调用,但是如果我们想要在比较特殊的环境下启动java进程,譬如在web server下(例如Tomcat)调用获取hdfs的信息,则不能够成功;或比如通过java -jar/-cp的方式来进行调用,得到的FileSystem.get(conf)并不是我们想要的。比如如果在本机执行该方法,就会得到本机磁盘相关文件系统,只有通过hadoop jar的方式调用返回DistributedFileSystem。
 
FileSystem类中还有一个方法,可以根据相应的URI来得到对应的FileSystem:
 
Java代码  收藏代码
  1. /** 
  2.  * Get a filesystem instance based on the uri, the passed 
  3.  * configuration and the user 
  4.  * @param uri of the filesystem 
  5.  * @param conf the configuration to use 
  6.  * @param user to perform the get as 
  7.  * @return the filesystem instance 
  8.  * @throws IOException 
  9.  * @throws InterruptedException 
  10.  */  
  11. public static FileSystem get(final URI uri, final Configuration conf,  
  12.       final String user) throws IOException, InterruptedException {  
 
 
从hadoop file system环境中查找对应hadoop defaultFS配置:
 
Xml代码  收藏代码
  1. <property>  
  2.     <name>fs.defaultFS</name>  
  3.     <value>hdfs://ns1</value>  
  
 
就会曝出以下的错误,提示缺少一个类定义:
 
Java代码  收藏代码
  1. Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/util/PlatformName  
  2. at org.apache.hadoop.security.UserGroupInformation.getOSLoginModuleName(UserGroupInformation.java:303)  
  3. at org.apache.hadoop.security.UserGroupInformation.<clinit>(UserGroupInformation.java:348)  
  4. at org.apache.hadoop.fs.FileSystem$Cache$Key.<init>(FileSystem.java:2590)  
  5. at org.apache.hadoop.fs.FileSystem$Cache$Key.<init>(FileSystem.java:2582)  
  6. at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2448)  
  7. at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:367)  
  8. at com.xxxx.HdfsMain.main(HdfsMain.java:21)  
  9. Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.util.PlatformName  
  10. at java.net.URLClassLoader$1.run(URLClassLoader.java:366)  
  11. at java.net.URLClassLoader$1.run(URLClassLoader.java:355)  
  12. at java.security.AccessController.doPrivileged(Native Method)  
  13. at java.net.URLClassLoader.findClass(URLClassLoader.java:354)  
  14. at java.lang.ClassLoader.loadClass(ClassLoader.java:423)  
  15. at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)  
  16. at java.lang.ClassLoader.loadClass(ClassLoader.java:356)  
  17. ... 7 more  
 
 
通过在网上查找的说法,此种情况下需要额外添加hadoop-auth的相关依赖:
 
Xml代码  收藏代码
  1. <dependency>  
  2.      <groupId>org.apache.hadoop</groupId>  
  3.      <artifactId>hadoop-auth</artifactId>  
  4.      <version>2.2.0</version>  
  5. </dependency>  
 
 
但是jar包添加进去后仍然不能够奏效,
 
Java代码  收藏代码
  1. Exception in thread "main" java.io.IOException: No FileSystem for scheme: hdfs  
  2. at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2421)  
  3. at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2428)  
  4. at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:88)  
  5. at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2467)  
  6. at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2449)  
  7. at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:367)   
 
 
经过查看源代码,可以看出SERVICE_FILE_SYSTEMS中并没有存在hdfs中scheme:
 
Java代码  收藏代码
  1. public static Class<? extends FileSystem> getFileSystemClass(String scheme,  
  2.     Configuration conf) throws IOException {  
  3.   if (!FILE_SYSTEMS_LOADED) {  
  4.     loadFileSystems();  
  5.   }  
  6.   Class<? extends FileSystem> clazz = null;  
  7.   if (conf != null) {  
  8.     clazz = (Class<? extends FileSystem>) conf.getClass("fs." + scheme + ".impl"null);  
  9.   }  
  10.   if (clazz == null) {  
  11.     clazz = SERVICE_FILE_SYSTEMS.get(scheme);  
  12.   }  
  13.   if (clazz == null) {  
  14.     throw new IOException("No FileSystem for scheme: " + scheme);  
  15.   }  
  16.   return clazz;  
  17. }  
 
 
可以手动采用Configuration设置fs.[filesystemname].impl的方式,手动将DistributedFileSystem注册进去:
 
Java代码  收藏代码
  1. conf.set("fs.hdfs.impl", DistributedFileSystem.class.getName());  
 
 
这样启动后发现仍然有坑,因为ns1并不是真实的网络地址,地址配置在hdfs-site.xml文件中,我们的NameNode是两个随时可互相切换的HA服务器:
 
 
 
 
Xml代码  收藏代码
  1. <property>  
  2.     <name>dfs.nameservices</name>  
  3.     <value>ns1</value>  
  4.   </property>  
  5.   
  6.   <property>  
  7.     <name>dfs.ha.namenodes.ns1</name>  
  8.     <value>nn1,nn2</value>  
  9.   </property>  
  10.   
  11.   <property>  
  12.     <name>dfs.namenode.rpc-address.ns1.nn1</name>  
  13.     <value>xxx1.cn:8020</value>  
  14.   </property>  
  15.   
  16.   <property>  
  17.     <name>dfs.namenode.rpc-address.ns1.nn2</name>  
  18.     <value>xxx2.cn:8020</value>  
  19.   </property>  
 
 
于是将fileSystem设置成其中的一台服务器,
 
fileSystem = FileSystem.get(URI.create("hdfs://xxx1.cn:8020"), conf)
 
这样终于成功了,注意,如果你连接上的是一个standby服务器,是不能够Read成功的!只有连接上active状态的服务器才能成功,那么如何确定哪台服务器当时是active呢,可以通过命令:
 
Java代码  收藏代码
  1. hdfs haadmin -getServiceState nn1  
  2. standby  
  3.    
  4. hdfs haadmin -getServiceState nn2  
  5. active  
 
 
这表示nn2是active NameNode服务器。
 
那么问题就来了,如果这样的话,当NameNode发生自动切换时,是不能够智能地发生切换操作的,如何避免这个问题?
 
在Hadoop技术内幕 hadoop common和hdfs架构设计原理与实现一书中,专门有一章节介绍hadoop hdfs configuration的设置。


  
 
 
从其中可以看出整个Configuration的加载过程,如果我们在构造FileSystem的时候,加载服务端中的两个核心文件,比如将代码写成下面这种,是否能够最终成功呢?
 
Java代码  收藏代码
  1. String uri = “/file/config";  
  2. Configuration conf = new Configuration();  
  3. conf.addResource(new Path("/home/xxxx/hadoop/etc/hadoop/core-site.xml"));  
  4. conf.addResource(new Path("/home/xxxx/hadoop/etc/hadoop/hdfs-site.xml"));  
  5. fileSystem = FileSystem.get(conf);  
  6. FileStatus[] fs = fileSystem.listStatus(new Path(uri));  
  7. for (FileStatus f : fs) {  
  8.      System.out.println(f.getPath());  
  9. }  
 
 
答案是可以的,甚至都不需要采用带URI的函数。虽然绕了个大圈回到了原点,解决办法也非常简单,但通过这个过程的分析,可以使得我们可以熟悉整个FileSystem初始化的过程,也算是收获不小吧。
分享到:
评论

相关推荐

    java整合spring和hadoop HDFS全部jar

    首先,Java是编写应用程序的通用编程语言,它提供了丰富的库和框架来支持各种任务,包括与Spring框架的集成和对Hadoop HDFS的访问。 Spring是一个开源的应用程序框架,它主要用于简化Java企业级应用的开发。它提供...

    访问hdfs用到的客户端jar包

    这些jar包共同构建了访问HDFS所需的完整环境,开发者可以将它们加入到Java项目的类路径中,以编写和运行与HDFS交互的应用程序。例如,使用`FileSystem`接口创建连接,使用`FSDataInputStream`和`FSDataOutputStream`...

    hadoop之hdfs中所依赖jar

    这些JAR包包含了Hadoop的相关API和实现,使得用户可以通过编程方式操作HDFS。 标题"hadop之hdfs中所依赖jar"指出的关键点是,为了成功地进行HDFS操作,必须确保正确地引入了必要的JAR包。这里提到的"Hadoop之上传...

    java操作Hadoop源码之HDFS Java API操作-上传文件

    总之,通过Hadoop的HDFS Java API,我们可以方便地在Java应用中与HDFS进行集成,实现文件的上传、下载等操作。理解并熟练掌握这些API,对于开发分布式应用,尤其是在大数据处理场景中,是至关重要的。在实际项目中,...

    java操作Hadoop源码之HDFS Java API操作-创建目录

    在项目中添加所有必要的jar包,这些通常包括`hadoop-common.jar`、`hadoop-hdfs.jar`等。在描述中提到的压缩包里,你应该能找到这些必要的依赖,确保将它们添加到项目的类路径中,以便能调用HDFS的API。 在Java代码...

    hadoop-hdfs-2.6.5-API文档-中文版.zip

    标签:apache、hdfs、hadoop、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...

    基于Hadoop的分布式系统依赖的所有JAR包

    HDFS的JAR包包含了实现文件系统接口的类,如`hadoop-hdfs-client.jar`,以及在集群中运行的DataNode和NameNode的服务器端组件,如`hadoop-hdfs.jar`。 2. **MapReduce**:Hadoop的MapReduce是一种编程模型,用于大...

    hadoop-hdfs-2.7.3-API文档-中英对照版.zip

    标签:apache、hdfs、hadoop、jar包、java、API文档、中英对照版; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准...

    hdfs_video_jar.zip_HDFS video_Hadoop 文件_hdfs_hdfs下MP4视频播放

    在Hadoop平台上打开和播放MP4文件并不像在本地文件系统上那么简单,因为HDFS不提供直接的流式访问支持。通常,我们需要通过Hadoop的API或特定的工具来实现。例如,可以使用`hadoop fs`命令行工具来查看和下载HDFS上...

    hadoop-hdfs-2.7.3-API文档-中文版.zip

    标签:apache、hdfs、hadoop、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...

    hadoop-hdfs-client-2.9.1-API文档-中英对照版.zip

    标签:apache、hadoop、hdfs、client、中英对照文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准...

    Hadoop2.2.0 HDFS开发依赖的jar包

    在Hadoop2.2.0中,`hadoop-common-2.2.0.jar`是必不可少的。 2. **HDFS Client**:提供与HDFS交互的客户端API,包括文件操作、文件系统管理和故障检测。对应的jar包是`hadoop-hdfs-client-2.2.0.jar`,它包含了所有...

    运行hadoop jar

    标题 "运行hadoop jar" 涉及到的是在Hadoop环境中执行自定义Java应用程序的过程。这个过程通常用于分布式计算,比如MapReduce任务。在Hadoop生态系统中,`hadoop jar` 是一个命令行工具,它允许用户通过指定的JAR...

    hadoop的各种jar包

    本文将详细介绍如何在Eclipse中使用Hadoop的各种JAR包,包括HDFS、MapReduce、YARN、HTTPFS和KMS,以实现高效的数据操作。 首先,我们需要理解这些组件在Hadoop生态系统中的角色: 1. HDFS(Hadoop Distributed ...

    hadoop-hdfs-2.5.1-API文档-中文版.zip

    标签:apache、hadoop、hdfs、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心...

    elcipse java hadoop操作hdfs的api

    在Hadoop生态系统中,Java API是开发者与HDFS(Hadoop Distributed File System)进行交互的主要方式。本资料主要涵盖了如何使用Eclipse环境进行Java开发,利用Hadoop的HDFS API来操作分布式文件系统。以下是对这些...

    hadoop-jar.zip

    开发者通常会将编写好的Java程序与依赖的Hadoop库一起打包成jar文件,然后通过`hadoop jar`命令在Hadoop集群上运行这个jar文件,执行MapReduce任务。 例如,以下是一个简单的`hadoop jar`命令执行流程: ```bash ...

    win10下编译过的hadoop jar包--hadoop-2.7.2.zip

    Hadoop是大数据处理领域的一个核心框架,由Apache软件基金会开发,它主要分为两个主要部分:Hadoop Distributed File System (HDFS) 和 MapReduce。Hadoop 2.7.2 版本是在Hadoop 2.x系列中的一个重要版本,带来了...

    hadoop 所用的jar包

    在编程时,将这些JAR包导入工程中是确保Hadoop程序正确运行的关键步骤。 首先,我们来了解Hadoop的主要组件和它们对应的JAR包: 1. **Hadoop Common**:这是Hadoop的基础模块,提供了各种通用工具和服务,包括文件...

    hadoop-2.7.2-hbase-jar.tar.gz

    在开发层面,"hadoop-2.7.2-hbase-jar"提供了Java API,允许开发者编写HBase客户端程序,进行数据的增删查改操作。同时,HBase还支持使用HBase Shell,这是一个基于JRuby的命令行工具,用户可以通过它直接与HBase...

Global site tag (gtag.js) - Google Analytics