hadoop 文件上传

hdsf 本质上就是一个分布式文件系统,只是相对于普通计算机来说,它可以很容易横向扩展,自带高可用机制。

我们要在Hadoop做MapReduce计算的时候,就需要把写好的程序打成jar包放到hdfs上。hadoop提供多种方式方式让你能够把文件放入hdfs,比如 自带的shell命令行客户端put命令,java客户端的FileSystem,REST的HDFS API(WebHDFS与HttpFS)。

命令行上传

hadoop shell 的 put 命令直接把本地文件上传到hdfs。

使用方法:hadoop fs -put <localsrc> ... <dst>

从本地文件系统中复制单个或多个源路径到目标文件系统。也支持从标准输入中读取输入写入目标文件系统。
hadoop fs -put localfile /user/hadoop/hadoopfile
hadoop fs -put localfile1 localfile2 /user/hadoop/hadoopdir
hadoop fs -put localfile hdfs://host:port/hadoop/hadoopfile
hadoop fs -put - hdfs://host:port/hadoop/hadoopfile
从标准输入中读取输入。
返回值:

成功返回0,失败返回-1。

hadoop shell 官方文档:http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_shell.html

Java客户端上传

我们做工程化、平台化后,需要通过程序与hadoop进行交换,hadoop提供了FileSystem 工具类供我们使用。

FileSystem官方文档:http://hadoop.apache.org/docs/current/api/org/apache/hadoop/fs/FileSystem.html

普通上传

普遍上传很简单,直接构建FileSystem的实例,调用API上传即可。需要注意的是fs.defaultFS这个配置项的值是活动的namenode地址+端口。

eg.1

public class CopyToHDFS {
    public static void main(String[] args) throws IOException {
         
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://active.namenode.host:9000");
         
        FileSystem fs = FileSystem.get(conf);
         
        fs.copyFromLocalFile(new Path("/home/lance/log.txt"), new Path("/log"));
    }
}

eg.2

import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
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.IOException;
import java.io.InputStream;

public class HdfsUpload {

    public static void main(String[] args) throws IOException {

        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://active.namenode.host:9000");
        FileSystem fs = FileSystem.get(conf);

        String remoteDst = "/user/hive/devbak/itclj/abc112234.txt";
        File inputFile = new File("D:/abc112233.txt");
        InputStream in = FileUtils.openInputStream(inputFile);


        FSDataOutputStream out = fs.create(new Path(remoteDst));
        IOUtils.copyBytes(in, out, conf);
    }

}

eg.3 通过代理账号上传

package com.itclj;

import com.itclj.kerberos.KerberosLogin;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.PrivilegedExceptionAction;

/**
 * @Author lujun.chen
 * @Date 2020/2/1 13:33
 * @Version 1.0
 */
public class HdfsUpload {

    public static void main(String[] args) throws IOException, InterruptedException {

        KerberosLogin login = new KerberosLogin();
        login.login();

        //直接上传
        //upload();

        //通过代理账号上传
        userProxyUpload();
    }


    public static void upload() throws IOException {
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://dptestservice1");//HA 模式的Hadoop集群
        //FileSystem fs = FileSystem.get(new URI("hdfs://s01cq-app-196-43-msxf.host:9000"), conf, "hive");
        FileSystem fs = FileSystem.get(conf);

        String remoteDst = "/user/hive/devbak/itclj/abc112234.txt";
        File inputFile = new File("D:/abc112233.txt");
        InputStream in = FileUtils.openInputStream(inputFile);


        FSDataOutputStream out = fs.create(new Path(remoteDst));
        IOUtils.copyBytes(in, out, conf);

        out.close();
        in.close();
        fs.close();

        System.out.println("===================");
    }

    public static void userProxyUpload() throws IOException, InterruptedException {
        String userProxy = "dsp";
        UserGroupInformation currentUser = UserGroupInformation.getCurrentUser();
        UserGroupInformation proxyUser = UserGroupInformation.createProxyUser(userProxy, currentUser);
        boolean rest = proxyUser.doAs(new PrivilegedExceptionAction<Boolean>() {

            public Boolean run() throws Exception {
                upload();
                return true;
            }
        });

        System.out.print("rest=" + rest);
    }

}

eg.4 上传限流

@Override
public HdfsOptVO upload(String path, InputStream inputStream) {
    try (FileSystem fs = buildFileSystem()) {
        try (FSDataOutputStream out = fs.create(new Path(path))) {
            DataTransferThrottler throttler = new DataTransferThrottler(hdfsDataTransferThrottlerSize);//限流
            byte buf[] = new byte[hdfsBufferSize];
            int bytesRead = inputStream.read(buf);
            while (bytesRead >= 0) {
                out.write(buf, 0, bytesRead);
                bytesRead = inputStream.read(buf);
                throttler.throttle(bytesRead);
            }
            //IOUtils.copyBytes(inputStream, out, 4096);
            inputStream.close();
        }
    } catch (Exception ex) {
        logger.error("HDFS文件上传失败,path: {}", path, ex);
        throw new DspException(CodeEnum.HDFS_OPT_UPLOAD_ERROR.getCode(), "文件上传出错," + ex.getMessage());
    }

    return new HdfsOptVO.Builder().hdfsUri(HDFS_PROTOCOL + path).build();
}

HA模式的hadoop集群文件上传

HA模式的Hadoop集群文件上传,代码和普通模式都一样的,fs.defaultFS配置项改为集群名称(hdfs://dptestservice1),但是单纯改这个值肯定是不行的,系统会报如下错误:

Exception in thread "main" java.lang.IllegalArgumentException: java.net.UnknownHostException: dptestservice1

主要还是工程缺少必要的Hadoop属性配置,配置属性方式一般有两种:一种是直接把hadoop的配置文件放到工程目录下,在配置文件里面设置属性;一种是如上所示,用set方法设置。

以下就是所需的关键属性,属性值得和自己集群的配置的属性值一样。

core-site.xml

<configuration>
  <property>
    <name>fs.defaultFS</name>
    <value>hdfs://dptestservice1</value>
  </property>
</configuration>  

hdfs-site.xml

<configuration>

  <property>
    <name>dfs.nameservices</name>
    <value>dptestservice1</value>
  </property>
  
  <property>
    <name>dfs.ha.namenodes.dptestservice1</name>
    <value>namenode148,namenode133</value>
  </property>
  
  <property>
    <name>dfs.namenode.rpc-address.dptestservice1.namenode148</name>
    <value>s01cq-app-196-39-itclj.host:9000</value>
  </property>
  
  <property>
    <name>dfs.namenode.rpc-address.dptestservice1.namenode133</name>
    <value>s01cq-app-196-43-itclj.host:9000</value>
  </property>
  
  <property>
    <name>dfs.client.failover.proxy.provider.dptestservice1</name>
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
  </property>
  
</configuration>  

eg

package com.itclj;

import com.itclj.kerberos.KerberosLogin;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
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.IOException;
import java.io.InputStream;

/**
 * @Author lujun.chen
 * @Date 2020/2/1 13:33
 * @Version 1.0
 */
public class HdfsUpload {

    public static void main(String[] args) throws IOException {

        // 集群开启了开启了kerberos 认证的,需要先进行kerberos认证。
        KerberosLogin login = new KerberosLogin();
        login.login();


        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://dptestservice1");//HA 模式的Hadoop集群
        FileSystem fs = FileSystem.get(conf);

        String remoteDst = "/user/hive/devbak/itclj/abc112234.txt";
        File inputFile = new File("D:/abc112233.txt");
        InputStream in = FileUtils.openInputStream(inputFile);


        FSDataOutputStream out = fs.create(new Path(remoteDst));
        IOUtils.copyBytes(in, out, conf);
    }

}

工程代码:https://github.com/clj198606061111/hadoop-client-demo/blob/master/src/main/java/com/itclj/HdfsUpload.java

REST的API上传

hadoop提供了2套REST的API,WebHDFS与HttpFS。

  • 两者都是基于REST的HDFS API,使得一个集群外的host可以不用安装HADOOP和JAVA环境就可以对集群内的HADOOP进行访问,并且client不受语言的限制。
  • WebHDFS是HDFS内置的、默认开启的一个服务,而HttpFS是HDFS一个独立的服务,若使用需要手动安装(CDH中安装HDFS时将HttpFS勾选上即可)。
  • WebHDFS是HortonWorks开发的,然后捐给了Apache;而HttpFS是Cloudera开发的,也捐给了Apache。
  • 当client请求某文件时,WebHDFS会将其重定向到该资源所在的datanode,而HttpFs相等于一个“网关”,所有的数据先传输到该httpfs server,再由该httpfs server传输到client。

WebHDFS

官方文档:https://hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/WebHDFS.html#Open_and_Read_a_File

HttpFS

官方文档:http://hadoop.apache.org/docs/current/hadoop-hdfs-httpfs/index.html

  • 1
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值