客户端用java api 远程操作HDFS以及远程提交MR任务(源码和异常处理)

转载 2013年12月05日 15:16:47

两个类,一个HDFS文件操作类,一个是wordcount 词数统计类,都是从网上看来的。上代码:

[java] view plaincopy
  1. package mapreduce;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.BlockLocation;  
  8. import org.apache.hadoop.fs.FSDataInputStream;  
  9. import org.apache.hadoop.fs.FSDataOutputStream;  
  10. import org.apache.hadoop.fs.FileStatus;  
  11. import org.apache.hadoop.fs.FileSystem;  
  12. import org.apache.hadoop.fs.Path;  
  13. import org.apache.hadoop.hdfs.DistributedFileSystem;  
  14. import org.apache.hadoop.hdfs.protocol.DatanodeInfo;  
  15. import org.apache.hadoop.io.IOUtils;  
  16. /** 
  17.  * file operation on HDFS 
  18.  * @author liuxingjiaofu 
  19.  * 
  20.  */  
  21. public class HDFS_File {  
  22.     //read the file from HDFS  
  23.     public void ReadFile(Configuration conf, String FileName){  
  24.       try{  
  25.             FileSystem hdfs = FileSystem.get(conf);  
  26.             FSDataInputStream dis = hdfs.open(new Path(FileName));  
  27.             IOUtils.copyBytes(dis, System.out, 4096false);   
  28.              dis.close();  
  29.         }catch (IOException e) {  
  30.             // TODO Auto-generated catch block  
  31.             e.printStackTrace();  
  32.         }  
  33.     }  
  34.     //copy the file from HDFS to local  
  35.     public void GetFile(Configuration conf, String srcFile, String dstFile){  
  36.         try {  
  37.               FileSystem hdfs = FileSystem.get(conf);  
  38.               Path srcPath = new Path(srcFile);  
  39.               Path dstPath = new Path(dstFile);  
  40.               hdfs.copyToLocalFile(true,srcPath, dstPath);  
  41.         }catch (IOException e) {  
  42.             // TODO Auto-generated catch block  
  43.             e.printStackTrace();  
  44.         }  
  45.     }  
  46.     //copy the local file to HDFS  
  47.     public void PutFile(Configuration conf, String srcFile, String dstFile){  
  48.     try {  
  49.           FileSystem hdfs = FileSystem.get(conf);  
  50.           Path srcPath = new Path(srcFile);  
  51.           Path dstPath = new Path(dstFile);  
  52.           hdfs.copyFromLocalFile(srcPath, dstPath);  
  53.         } catch (IOException e) {  
  54.             // TODO Auto-generated catch block  
  55.             e.printStackTrace();  
  56.         }  
  57.     }  
  58.     //create the new file  
  59.     public FSDataOutputStream CreateFile(Configuration conf, String FileName){  
  60.     try {     
  61.           FileSystem hdfs = FileSystem.get(conf);  
  62.           Path path = new Path(FileName);  
  63.           FSDataOutputStream outputStream = hdfs.create(path);  
  64.           return outputStream;  
  65.         } catch (IOException e) {  
  66.         // TODO Auto-generated catch block  
  67.         e.printStackTrace();  
  68.         }  
  69.         return null;  
  70.     }  
  71.     //rename the file name  
  72.     public boolean ReNameFile(Configuration conf, String srcName, String dstName){  
  73.     try {  
  74.             Configuration config = new Configuration();  
  75.             FileSystem hdfs = FileSystem.get(config);  
  76.             Path fromPath = new Path(srcName);  
  77.             Path toPath = new Path(dstName);  
  78.             boolean isRenamed = hdfs.rename(fromPath, toPath);  
  79.             return isRenamed;  
  80.         }catch (IOException e) {  
  81.             // TODO Auto-generated catch block  
  82.             e.printStackTrace();  
  83.         }  
  84.         return false;  
  85.     }  
  86.     //delete the file  
  87.     // tyep = true, delete the directory  
  88.     // type = false, delete the file  
  89.     public boolean DelFile(Configuration conf, String FileName, boolean type){  
  90.         try {  
  91.               FileSystem hdfs = FileSystem.get(conf);  
  92.               Path path = new Path(FileName);  
  93.               boolean isDeleted = hdfs.delete(path, type);  
  94.               return isDeleted;  
  95.         }catch (IOException e) {  
  96.             // TODO Auto-generated catch block  
  97.             e.printStackTrace();  
  98.         }  
  99.         return false;  
  100.     }  
  101.     //Get HDFS file last modification time  
  102.     public long GetFileModTime(Configuration conf, String FileName){  
  103.     try{  
  104.               FileSystem hdfs = FileSystem.get(conf);  
  105.               Path path = new Path(FileName);  
  106.               FileStatus fileStatus = hdfs.getFileStatus(path);  
  107.               long modificationTime = fileStatus.getModificationTime();  
  108.               return modificationTime;  
  109.         }catch(IOException e){  
  110.             e.printStackTrace();  
  111.         }  
  112.         return 0;  
  113.     }  
  114.     //check if a file  exists in HDFS  
  115.     public boolean CheckFileExist(Configuration conf, String FileName){  
  116.     try{              
  117.               FileSystem hdfs = FileSystem.get(conf);  
  118.               Path path = new Path(FileName);  
  119.               boolean isExists = hdfs.exists(path);  
  120.               return isExists;  
  121.         }catch(IOException e){  
  122.             e.printStackTrace();  
  123.         }  
  124.         return false;  
  125.     }  
  126.     //Get the locations of a file in the HDFS cluster  
  127.     public List<String []> GetFileBolckHost(Configuration conf, String FileName){  
  128.         try{  
  129.               List<String []> list = new ArrayList<String []>();  
  130.               FileSystem hdfs = FileSystem.get(conf);  
  131.               Path path = new Path(FileName);  
  132.               FileStatus fileStatus = hdfs.getFileStatus(path);  
  133.       
  134.               BlockLocation[] blkLocations = hdfs.getFileBlockLocations(fileStatus, 0, fileStatus.getLen());  
  135.                 
  136.               int blkCount = blkLocations.length;  
  137.               for (int i=0; i < blkCount; i++) {  
  138.                 String[] hosts = blkLocations[i].getHosts();  
  139.                 list.add(hosts);  
  140.                }  
  141.               return list;  
  142.             }catch(IOException e){  
  143.                 e.printStackTrace();  
  144.             }  
  145.             return null;  
  146.     }  
  147.     //Get a list of all the nodes host names in the HDFS cluster  
  148.     // have no authorization to do this operation  
  149.     public String[] GetAllNodeName(Configuration conf){  
  150.         try{  
  151.               FileSystem fs = FileSystem.get(conf);  
  152.               DistributedFileSystem hdfs = (DistributedFileSystem) fs;  
  153.               DatanodeInfo[] dataNodeStats = hdfs.getDataNodeStats();  
  154.               String[] names = new String[dataNodeStats.length];  
  155.               for (int i = 0; i < dataNodeStats.length; i++) {  
  156.                   names[i] = dataNodeStats[i].getHostName();  
  157.               }  
  158.               return names;  
  159.         }catch(IOException e){  
  160.             System.out.println("error!!!!");  
  161.             e.printStackTrace();  
  162.         }  
  163.         return null;  
  164.     }  
  165. }  

wordcount

[java] view plaincopy
  1. package mapreduce;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.StringTokenizer;  
  5.   
  6. import org.apache.hadoop.conf.Configuration;  
  7. import org.apache.hadoop.fs.Path;  
  8. import org.apache.hadoop.io.IntWritable;  
  9. import org.apache.hadoop.io.LongWritable;  
  10. import org.apache.hadoop.io.Text;  
  11.   
  12. import org.apache.hadoop.mapreduce.Job;  
  13. import org.apache.hadoop.mapreduce.Mapper;  
  14. import org.apache.hadoop.mapreduce.Reducer;  
  15. import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;  
  16. import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;  
  17. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;  
  18.   
  19. public class mywordcount {  
  20.     public static  class wordcountMapper extends  
  21.         Mapper<LongWritable, Text, Text, IntWritable>{  
  22.         private final static IntWritable one = new IntWritable(1);  
  23.         private Text word = new Text();  
  24.         public void map(LongWritable key, Text value, Context context)throws IOException, InterruptedException{  
  25.             String line = value.toString();  
  26.             StringTokenizer itr = new StringTokenizer(line);  
  27.             while(itr.hasMoreElements()){  
  28.                 word.set(itr.nextToken());  
  29.                 context.write(word, one);  
  30.             }  
  31.         }  
  32.     }  
  33.     public static  class wordcountReducer extends  
  34.         Reducer<Text, IntWritable, Text, IntWritable>{  
  35.         public void reduce(Text key, Iterable<IntWritable>values, Context context)throws IOException, InterruptedException{  
  36.             int sum = 0;  
  37.             for (IntWritable str : values){  
  38.                 sum += str.get();  
  39.             }  
  40.             context.write(key, new IntWritable(sum));  
  41.         }  
  42.     }  
  43.     /** 
  44.      * 2 args, the file you want to count words from and the directory you want to save the result 
  45.      * @param args /home/hadooper/testmp/testtext /home/hadooper/testmp/testresult 
  46.      * @throws Exception 
  47.      */  
  48.     public static  void main(String args[])throws Exception{  
  49.         //首先定义两个临时文件夹,这里可以使用随机函数+文件名,这样重名的几率就很小。  
  50.         String dstFile = "temp_src";  
  51.         String srcFile = "temp_dst";  
  52.         //这里生成文件操作对象。  
  53.         HDFS_File file = new HDFS_File();  
  54.           
  55.         Configuration conf = new Configuration();  
  56.         // must!!!  config the fs.default.name be the same to the value in core-site.xml  
  57.         conf.set("fs.default.name","hdfs://node1");  
[java] view plaincopy
  1.         conf.set("mapred.job.tracker","node1:54311");  
  2.   
  3.         //从本地上传文件到HDFS,可以是文件也可以是目录  
  4.         file.PutFile(conf, args[0], dstFile);  
  5.           
  6.         System.out.println("up ok");  
  7.         Job job = new Job(conf, "mywordcount");       
  8.         job.setJarByClass(mywordcount.class);  
  9.           
  10.         job.setInputFormatClass(TextInputFormat.class);  
  11.           
  12.         job.setOutputKeyClass(Text.class);  
  13.         job.setOutputValueClass(IntWritable.class);  
  14.           
  15.         job.setMapperClass(wordcountMapper.class);  
  16.         job.setReducerClass(wordcountReducer.class);  
  17.         job.setCombinerClass(wordcountReducer.class);  
  18.         //注意这里的输入输出都应该是在HDFS下的文件或目录       
  19.         FileInputFormat.setInputPaths(job, new Path(dstFile));  
  20.         FileOutputFormat.setOutputPath(job, new Path(srcFile));  
  21. //开始运行  
  22.         job.waitForCompletion(true);  
  23.         //从HDFS取回文件保存至本地  
  24.         file.GetFile(conf, srcFile, args[1]);  
  25.         System.out.println("down the result ok!");  
  26. //删除临时文件或目录  
  27.         file.DelFile(conf, dstFile, true);  
  28.         file.DelFile(conf, srcFile, true);  
  29.         System.out.println("delete file on hdfs ok!");  
  30.     }  
  31. }  


期间,遇到几个错误:

1.HDFS版本问题--Call to node1/172.*.*.*:8020 failed on local exception: java.io.EOFException

main() {…… 
  Configuration conf = new Configuration();
  conf.set("fs.default.name","hdfs://node1");//与conf/core-site里的值对应,必须
  HDFS_File file = new HDFS_File();
  //print all the node name
  String[] host_name = file.GetAllNodeName(conf); 
……}
public String[] GetAllNodeName(Configuration conf){
  try{
    // Configuration config = new Configuration();
     FileSystem fs = FileSystem.get(conf);
     DistributedFileSystem hdfs = (DistributedFileSystem) fs;
     DatanodeInfo[] dataNodeStats = hdfs.getDataNodeStats();
     String[] names = new String[dataNodeStats.length];
     for (int i = 0; i < dataNodeStats.length; i++) {
         names[i] = dataNodeStats[i].getHostName();
     }
     return names;
  }catch(IOException e){
   System.out.println("eeeeeeeeeeeeeeeeeeeerror!!!!");
   e.printStackTrace();
  }
  return null;
 }
异常:
eeeeeeeeeeeeeeeeeeeerror!!!!
java.io.IOException: Call to node1/172.10.39.250:8020 failed on local exception: java.io.EOFException
 at org.apache.hadoop.ipc.Client.wrapException(Client.java:775)
 at org.apache.hadoop.ipc.Client.call(Client.java:743)
 at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:220)
 at $Proxy0.getProtocolVersion(Unknown Source)
 at org.apache.hadoop.ipc.RPC.getProxy(RPC.java:359)
 at org.apache.hadoop.hdfs.DFSClient.createRPCNamenode(DFSClient.java:112)
 at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:213)
 at org.apache.hadoop.hdfs.DFSClient.<init>(DFSClient.java:176)
 at org.apache.hadoop.hdfs.DistributedFileSystem.initialize(DistributedFileSystem.java:82)
 at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:1378)
 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 mapreduce.HDFS_File.GetAllNodeName(HDFS_File.java:151)
 at mapreduce.File_Operation.main(File_Operation.java:15)
Caused by: java.io.EOFException
 at java.io.DataInputStream.readInt(DataInputStream.java:392)
 at org.apache.hadoop.ipc.Client$Connection.receiveResponse(Client.java:501)
 at org.apache.hadoop.ipc.Client$Connection.run(Client.java:446)
Exception in thread "main" java.lang.NullPointerException
 at mapreduce.File_Operation.main(File_Operation.java:16)
原因:版本问题,确保java中的jar包跟hadoop集群的jar包是相同版本的
2.HDFS
权限问题

 

org.apache.hadoop.security.AccessControlException: org.apache.hadoop.security.AccessControlException: Permission denied: user=hadooper, access=WRITE, inode="/user":root:supergroup:drwxr-xr-x

解决方案之
(1 added this entry to conf/hdfs-site.xml
<property>
<name>dfs.permissions</name>
<value>false</value>
</property> 
(2.放开 要写入目录 hadoop 目录的权限 , 命令如下 :$ hadoop fs -chmod 777 /user/
我用的是第2种方案

3.HDFS 2011-12-20 17:00:32 org.apache.hadoop.util.NativeCodeLoader <clinit>
警告: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

在Hadoop的配置文件core-site.xml中可以设置是否使用本地库: 
<property>
  <name>hadoop.native.lib</name>
  <value>true</value>
  <description>Should native hadoop libraries, if present, be used.</description>
</property>

Hadoop默认的配置为启用本地库。 
另外,可以在环境变量中设置使用本地库的位置:
export JAVA_LIBRARY_PATH=/path/to/hadoop-native-libs
有的时候也会发现Hadoop自带的本地库无法使用,这种情况下就需要自己去编译本地库了。在$HADOOP_HOME目录下,使用如下命令即可:
ant compile-native
编译完成后,可以在$HADOOP_HOME/build/native目录下找到相应的文件,然后指定文件的路径或者移动编译好的文件到默认目录下即可
我试了下,那个是64位的,我电脑是32位的,没有源代码,编译不了,那只好一段段程序的试,找出哪段代码出了这个警告,我的是
  try {
     FileSystem hdfs = FileSystem.get(conf);
     Path srcPath = new Path(srcFile);
     Path dstPath = new Path(dstFile);
     hdfs.copyToLocalFile(true,srcPath, dstPath);//定位到此句
  }catch (IOException e) {
 到了此步,便只能如此了,为什么呢,java不是跨平台的吗

4.MR-jar包缺失

ClassNotFoundException: org.codehaus.jackson.map.JsonMappingException
NoClassDefFoundError: org/apache/commons/httpclient/HttpMethod

添加jar包到java工程中

jackson-core-asl-1.5.2.jar
jackson-mapper-asl-1.5.2.jar

commons-httpclient-3.0.1.jar

我是不习惯将所有Jar包都加到工程里,觉得这样很容易便加多了,浪费时空。
完成第一次mapreduce,不错!

5.远程的JOB挂掉了,居然还能运行成功,发现是mapred.job.tracker属性没设,默认在local下运行,其值在namenode的mapred-site.xml中看

 conf.set("mapred.job.tracker","node1:54311");

配置完了,运行可以初始化,但是找不到mapper类:

信息: Task Id : attempt_201112221123_0010_m_000000_0, Status : FAILED
java.lang.RuntimeException: java.lang.ClassNotFoundException: mapreduce.mywordcount$wordcountMapper
 at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:996)
 at org.apache.hadoop.mapreduce.JobContext.getMapperClass(JobContext.java:212)
 at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:611)
 at org.apache.hadoop.mapred.MapTask.run(MapTask.java:325)
 at org.apache.hadoop.mapred.Child$4.run(Child.java:270)
 at java.security.AccessController.doPrivileged(Native Method)
 at javax.security.auth.Subject.doAs(Subject.java:396)
 at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1127)
 at org.apache.hadoop.mapred.Child.main(Child.java:264)

将程序打成jar包放到hadoop集群的jobtracker上可用,正常,结果也正确,但是在客户端运行却报上述错误,暂时还没解决。

总结

1.远程操作HDFS文件以及远程提交MR任务,必须配置的两项(其他暂时还没发现):

conf.set("fs.default.name","hdfs://node1");//与conf/core-site.xml里的值对应,必须 
conf.set("mapred.job.tracker","node1:54311");//mapred-site.xml

2.耐心分析问题,解决问题

相关文章推荐

java api 远程访问hdfs

java api 远程访问hdfs

HDFS远程连接 客户端权限错误

HDFS客户端的权限错误:Permission denied 搭建了一个Hadoop的环境,Hadoop集群环境部署在几个Linux服务器上,现在想使用windows上的Java客户端来操作...

从Java代码远程提交YARN MapReduce任务

http://blog.csdn.net/mercedesqq/article/details/16885115# 在Hadoop上运行MapReduce任务的标准做法是把代码打包到jar里...

从Java代码远程提交YARN MapReduce任务

在Hadoop上运行MapReduce任务的标准做法是把代码打包到jar里面,上传到服务器,然后用命令行启动。如果你是从一个Java应用中想要启动一个MapReduce,那么这个方法真是又土又麻烦。 ...

Hadoop 学习笔记八 任务远程提交--Java远程提交

Hadoop运行计算任务,大概有以下几种方式 把MapReduce任务打包到jar里,上传到服务器,用命令行启动 通过Java向Hadoop集群提交MapReduce任务 服务器的hadoop配置拷到...
  • xundh
  • xundh
  • 2017年05月03日 08:30
  • 412

Eclipse远程提交MapReduce任务到Hadoop集群

一、介绍 以前写完MapReduce任务以后总是打包上传到Hadoop集群,然后通过shell命令去启动任务,然后在各个节点上去查看Log日志文件,后来为了提高开发效率,需要找到通过Ecplise直接...

Java实现远程HDFS的文件操作(新建、上传、下载、删除)

通过java编程实现了远程HDFS的文件创建,上传,下载,删除等。Hadoop类库中最终面向用户提供的接口类是FileSystem,该类封装了几乎所有的文件操作,例如CopyToLocalFile、C...
  • dcxhun3
  • dcxhun3
  • 2015年11月23日 17:22
  • 5327

客户端用java api 远程操作HDFS以及远程提交MR任务(源码和异常处理)

两个类,一个HDFS文件操作类,一个是wordcount 词数统计类,都是从网上看来的。上代码: package mapreduce; import java.io.IOException; ...

远程HDFS文件的操作

因为手头项目涉及到远程HDFS文件的操作,所以打算学习一下相关操作。目前,网络上有很多操作HDFS文件的代码,但是它们基本上都没有描述清楚Configuration相关问题。经过摸索,终于实现远程HD...

Hadoop远程过程调用

远程过程调用(Remote Procedure Call, RPC)由1984年引入分布式计算领域,是解决分布式系统访问透明性的解决方案。远程过程调用让用户可以像调用本地方法一样调用另外一个应用程序提...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:客户端用java api 远程操作HDFS以及远程提交MR任务(源码和异常处理)
举报原因:
原因补充:

(最多只允许输入30个字)