Java API远程访问Hadoop

简介

在部署了Hadoop机器的服务器上, 可以直接使用hadoop相关命令操作HDFS文件系统,参考 hadoop命令;或者编写可用hadoop命令执行的代码打成jar包,在服务器上运行。

本文主要介绍如何利用Java API 在Windows或未进行Hadoop部署的Linux环境远程访问Hadoop的HDFS系统。

Jar包依赖

  • hadoop-hdfs
  • hadoop-common
  • hadoop-client
// Spring 依赖示例
dependencies {
    compile('org.apache.hadoop:hadoop-hdfs:3.1.0')
    compile('org.apache.hadoop:hadoop-common:3.1.0')
    compile('org.apache.hadoop:hadoop-client:3.1.0')
}

Java API远程访问

实现功能将本地文件存储到hdfs,拷贝hdfs文件到本地,示例代码如下:

package com.notepad.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI;

/**
 * Description: Hdfs远程访问示例
 * <p>
 * Create:       2018/6/21 23:59
 *
 * @author Yang Meng([email protected])
 */
public class HdfsProcess {

    /**
     * 构造FileSystem
     *
     * @return true, 构造成果
     * @throws Exception 构造异常
     */
    public boolean load() throws Exception {
        Configuration conf = new Configuration();
        conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
        fileSystem = FileSystem.get(new URI(HDFS_URI), conf, USER);
        return fileSystem != null;
    }

    /**
     * 根据指定的hdfs路径创建hdfs目录
     *
     * @param hdfsDir 指定的hdfs目录
     * @return true, hdfs目录构造完成
     * @throws Exception 构造异常
     */
    public boolean makeDir(Path hdfsDir) throws Exception {
        return fileSystem.exists(hdfsDir) || fileSystem.mkdirs(hdfsDir);
    }

    /**
     * 本地文件存储到hdfs目录
     *      示例:
     *          String localFile = "D:\\log\\text.demo";
     *          String hdfsDir = "/test/";
     *
     *          // 存储为hdfs://xxx/test/text.demo
     *          put(localFile, hdfsDir);
     *
     * @param localFile 本地文件路径
     * @param hdfsDir hdfs目录
     * @return true, 存储
     * @throws Exception 导入异常
     */
    public boolean put(String localFile, String hdfsDir) throws Exception {
        if (!makeDir(new Path(hdfsDir))) {
            return false;
        }
        File local = new File(localFile);
        if (!local.isFile()) {
            return false;
        }
        fileSystem.copyFromLocalFile(new Path(localFile), new Path(hdfsDir + "/" + local.getName()));
        return true;
    }

    /**
     * hdfs目录的文件存储到本地
     *      示例:
     *          String localDir = "D:\\log\\";
     *          String fileName = "text.demo";
     *          String hdfsDir = "/test/";
     *
     *          //将hdfs://xxx/test/text.demo存储到本地D:\\log\\
     *          get(hdfsDir, fileName, localDir);
     *
     * @param hdfsDir hdfs目录
     * @param fileName 指定文件
     * @param localDir 本地目录
     * @return true, 存储正常
     * @throws Exception 存储异常
     */
    public boolean get(String hdfsDir, String fileName, String localDir) throws Exception {
        InputStream in = fileSystem.open(new Path(hdfsDir + "/" + fileName));
        FileOutputStream out = new FileOutputStream(new File(localDir + "/" + fileName));
        IOUtils.copyBytes(in, out, 2048, true);
        return true;
    }

    private FileSystem fileSystem;
    private static final String HDFS_URI = "hdfs://{host}:{port}/";
    private static final String USER = "hdfs";
}

遇到的问题集合

  • Windows环境报错:failed to locate the winutils binary in the hadoop binary path java.io.IOException: Could not locate executable null\bin\winutils.exe in the hadoop binaryies.

    • 问题:缺失winutils.exe
    • 解决方法:
      下载winutils.exe,并放置在指定位置的bin目录下, 假设为放在D盘”D:\\bin\\”
      设置环境变量HADOOP_HOME 或代码中设置路径, System.setProperty("hadoop.home.dir", "D:\\")
  • Linux环境设置HADOOP_HOME

    • 解决方法:
      下载hadoop部署包,并设置HADOOP_HOME,修改用户目录下 .bashrc
    // .bashrc
    export HADOOP_HOME="xxx"
    
    // shell: 设置生效
    $ source ~/.bashrc
  • Linux环境报错:java.io.IOException: No FileSystem for scheme: hdfs

    • 解决方法:
      构造Configuration时显示设置 "org.apache.hadoop.hdfs.DistributedFileSystem"
    // 构造Configuration
    Configuration conf = new Configuration();
    conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
  • 报错:Exception in thread “main” java.net.ConnectException: Call From xx to yy

    • 解决方法
      利用HDFS的URI构造FileSystem
      URI: 参考hadoop的部署文件hdfs-site. xml中 “dfs.namenode.rpc-address”前缀的property对应的值作为uri。
    //hdfs uri
    URI hdfsUri = new URI("hdfs://{host}:{port}/");
    
    //无user
    FileSystem fileSystem = FileSystem.get(hdfsUri, new Configuration()));
    
    //有user: 针对有user的需设置user, 否则会报出无访问权限的错误
    String user = "HDFS"
    FileSystem userFileSystem = FileSystem.get(hdfsUri, new Configuration()), user);

参考

https://blog.csdn.net/cjf_wei/article/details/79303552

猜你喜欢

转载自blog.csdn.net/ymaini/article/details/80768352