如何使用Java API访问HDFS为目录设置配额

温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。

Fayson的github: https://github.com/fayson/cdhproject

提示:代码块部分可以左右滑动查看噢

1.文档编写目的


在开发应用使用Hadoop提供的hadoop-client API来访问HDFS并进行本地调试,本篇文章Fayson主要介绍如何使用Java API访问Kerberos环境下的HDFS并为目录设置配额。

  • 内容概述

1.环境准备

2.Kerberos环境为HDFS目录设置配额

3.配额测试及总结

  • 测试环境

1.CM和CDH版本为CDH5.14.3

2.OS为Redhat7.2

  • 前置条件

1.HDFS服务运行正常

2.JDK1.8

2.环境准备


1.在工程的pom.xml文件中添加Maven依赖

<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>2.6.0-cdh5.11.2</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.6.0-cdh5.11.2</version>
</dependency>

(可左右滑动)

2.创建一个hdfs/admin的Kerberos账号,用于以hdfs管理员身份管理HDFS

[root@cdh01 hdfs-admin-run]# kadmin.local 
kadmin.local:  addprinc hdfs/admin@FAYSON.COM
kadmin.local:  xst -norandkey -k hdfs.keytab hdfs/admin@FAYSON.COM

(可左右滑动)

使用如下命令查看导出的hdfs.keytab文件

[root@cdh01 ~]# klist -ek hdfs.keytab 

(可左右滑动)

3.获取集群krb5.conf文件,内容如下(非Kerberos集群可跳过此步)

[root@cdh01 ~]# vim /etc/krb5.conf
# Configuration snippets may be placed in this directory as well
includedir /etc/krb5.conf.d/
[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log
[libdefaults]
 dns_lookup_realm = false
 ticket_lifetime = 24h
 renew_lifetime = 7d
 forwardable = true
 rdns = false
 default_realm = FAYSON.COM
 #default_ccache_name = KEYRING:persistent:%{uid}
[realms]
 FAYSON.COM = {
  kdc = cdh01.fayson.com
  admin_server = cdh01.fayson.com
 }
[domain_realm]
 .fayson.com = FAYSON.COM
 fayson.com = FAYSON.COM

(可左右滑动)

4.通过Cloudera Manager下载HDFS客户端配置

3.编写代码通过API访问HDFS设置配额示例


1.将准备好的配置文件拷贝至工程的kb-conf目录下

2.创建conf.properties配置文件,内容如下:

kerberos.isenable=true
kerberos.debug=true
kerberos.principal=hdfs/admin@FAYSON.COM
kerberos.keytab=hdfs.keytab

(可左右滑动)

3.新建HDFSAdminUtils.java工具类,内容如下:

package com.cloudera.hdfs.utils;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import java.io.IOException;
/**
 * package: com.cloudera.hdfs.utils
 * describe: HDFSAdmin API 工具类
 * creat_user: Fayson
 * email: htechinfo@163.com
 * creat_date: 2018/6/8
 * creat_time: 上午11:01
 * 公众号:Hadoop实操
 */
public class HDFSAdminUtils {
    /**
     * 设置HDFS指定目录下文件总数
     * @param hdfsAdmin
     * @param path
     * @param quota
     */
    public static void setQuota(HdfsAdmin hdfsAdmin, Path path, long quota) {
        try {
            hdfsAdmin.setQuota(path, quota);
            System.out.println("成功设置HDFS的" + path.getName() + "目录文件数为:" + quota);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 设置HDFS指定目录目录空间大小
     * @param hdfsAdmin
     * @param path
     * @param quota
     */
    public static void setSpaceQuota(HdfsAdmin hdfsAdmin, Path path, long quota) {
        try {
            hdfsAdmin.setSpaceQuota(path, quota);
            System.out.println("成功设置HDFS的" + path.getName() + "目录空间大小为:" + quota);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 清除指定HDFS目录的所有配额限制
     * @param hdfsAdmin
     * @param path
     */
    public static void clrAllQuota(HdfsAdmin hdfsAdmin, Path path) {
        try {
            hdfsAdmin.clearSpaceQuota(path);
            hdfsAdmin.clearQuota(path);
            System.out.println("成功清除HDFS的" + path.getName() + "目录的配额限制");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(可左右滑动)

4.新建HDFSAdminTest.java类,内容如下:

package com.cloudera.hdfs.basic;
import com.cloudera.hdfs.utils.HDFSAdminUtils;
import com.cloudera.hdfs.utils.HDFSUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.client.HdfsAdmin;
import org.apache.hadoop.security.UserGroupInformation;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/**
 * package: com.cloudera.hdfs.basic
 * describe: 使用HDFS的Client Admin API操作HDFS,Kerberos环境下访问
 * creat_user: Fayson
 * email: htechinfo@163.com
 * creat_date: 2018/6/8
 * creat_time: 上午10:24
 * 公众号:Hadoop实操
 */
public class HDFSAdminTest {
    private static String confPath = System.getProperty("user.dir") + File.separator + "conf";
    public static void main(String[] args) {
        try {
            File file = new File(confPath + File.separator + "conf.properties");
            if(!file.exists()) {
                System.out.println("配置文件不存在");
                System.exit(0);
            }
            Properties properties = new Properties();
            properties.load(new FileInputStream(file));
            //初始化HDFS Configuration 配置
            Configuration configuration = HDFSUtils.initConfiguration(confPath);
            if(properties.getProperty("kerberos.isenable").equals("true")) {
                initKerberosENV(configuration, properties);
            }
            FileSystem fileSystem = FileSystem.get(configuration);
            HdfsAdmin hdfsAdmin = new HdfsAdmin(fileSystem.getUri(), configuration);
            //获取操作类型
            String operation = args[0];
            switch (operation) {
                case "setQuota":
                    HDFSAdminUtils.setQuota(hdfsAdmin, new Path(args[1]), Long.parseLong(args[2]));
                    break;
                case "setSpaceQuota":
                    HDFSAdminUtils.setSpaceQuota(hdfsAdmin, new Path(args[1]), Long.parseLong(args[2]));
                    break;
                case "clrAllQuota":
                    HDFSAdminUtils.clrAllQuota(hdfsAdmin, new Path(args[1]));
                    break;
                default:
                    System.out.print("操作类型错误");
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 初始化Kerberos环境
     */
    public static void initKerberosENV(Configuration conf, Properties properties) {
        System.setProperty("java.security.krb5.conf", confPath + File.separator + "krb5.conf");
        System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
        System.setProperty("sun.security.krb5.debug", properties.getProperty("kerberos.debug"));
        try {
            UserGroupInformation.setConfiguration(conf);
            UserGroupInformation.loginUserFromKeytab(properties.getProperty("kerberos.principal"), confPath + File.separator + properties.getProperty("kerberos.keytab"));
            System.out.println(UserGroupInformation.getCurrentUser());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(可左右滑动)

4.配额测试


将工程编译打包,上传至集群的服务器,封装为一个可执行的脚本测试。

1.使用mvn命令将工程编译,将生成的jar包拷贝至hdfs-admin-run/lib目录下

2.将工程kb-conf目录下的配置文件拷贝至conf目录下

3.修改run.sh脚本中JAVA的环境变量

#!/bin/bash

JAVA_HOME=/usr/java/jdk1.8.0_131-cloudera
for file in `ls lib/*jar`
do
    CLASSPATH=$CLASSPATH:$file
done
export CLASSPATH
${JAVA_HOME}/bin/java com.cloudera.hdfs.basic.HDFSAdminTest $@

(可左右滑动)

4.在命令行执行如下命令,为/testquota目录设置目录文件数为2

[root@cdh01 hdfs-admin-run]# sh run.sh setQuota /testquota 2

(可左右滑动)

向/testquota目录下put两个测试文件

[root@cdh01 hdfs-admin-run]# klist
[root@cdh01 hdfs-admin-run]# hadoop fs -ls /testquota
[root@cdh01 hdfs-admin-run]# hadoop fs -put run.sh /testquota
[root@cdh01 hdfs-admin-run]# hadoop fs -put /root/jdk-8u131-linux-x64.tar.gz /testquota

(可左右滑动)

通过设置了HDFS的/testquota目录的文件数量为2,经过测试将两个文件put到/testquota目录提示目录配额为2put的文件数已超出配额,不允许上传了。

5.为/testquota目录设置文件数量的配额同时设置目录空间大小为128MB

[root@cdh01 hdfs-admin-run]# sh run.sh setSpaceQuota /testquota 134217728

(可左右滑动)

向/testquota目录下put一个大于128MB的文件,进行测试

[root@cdh01 hdfs-admin-run]# klist
[root@cdh01 hdfs-admin-run]# hadoop fs -rmr /testquota/*
[root@cdh01 hdfs-admin-run]# hadoop fs -put /root/jdk-8u131-linux-x64.tar.gz /testquota

(可左右滑动)

通过测试可以看到put文件失败,文件大小已超出文件配额限制,可以看到我们设置的配额大小为128MB,put一个170多MB的文件,提示需要额外的384MB空间,通过该提示可以看出,目录配额大小是按照HDFS默认的3副本进行计算的。

6.清除文件配额限制

[root@cdh01 hdfs-admin-run]# sh run.sh clrAllQuota /testquota

(可左右滑动)

测试目录配额限制已取消

[root@cdh01 hdfs-admin-run]# hadoop fs -put /root/jdk-8u131-linux-x64.tar.gz /testquota
[root@cdh01 hdfs-admin-run]# hadoop fs -put run.sh /testquota
[root@cdh01 hdfs-admin-run]# hadoop fs -ls /testquota

(可左右滑动)

通过测试清除目录配额后可以没有限制的向/testquota目录put任意大小的文件和文件数。

5.总结


1.在通过Java API访问Kerberos环境的CDH集群时,如果要使用HdfsAdmin API则需要指定用户为hdfs用户,否则会提示没有权限操作。

2.可以通过Java程序调用HdfsAdmin的API接口设置HDFS目录的配额及清除目录配额操作。

3.设置空间配额大小时,单位精确到byte,设置配额文件数时,文件数含父目录数。

4.目录空间配额大小是按照默认HDFS设置的副本数进行计算的(如:HDFS的副本数为3,则占用目录的空间配额为:文件大小 * 3)。

5.通过API的方式设置了目录空间的配额,在CM界面是不会显示出来的。

GitHub源码地址:

https://github.com/fayson/cdhproject/tree/master/hdfsdemo/hdfs-admin-run

https://github.com/fayson/cdhproject/blob/master/hdfsdemo/src/main/java/com/cloudera/hdfs/basic/HDFSAdminTest.java

https://github.com/fayson/cdhproject/blob/master/hdfsdemo/src/main/java/com/cloudera/hdfs/utils/HDFSAdminUtils.java

提示:代码块部分可以左右滑动查看噢

为天地立心,为生民立命,为往圣继绝学,为万世开太平。 温馨提示:要看高清无码套图,请使用手机打开并单击图片放大查看。

推荐关注Hadoop实操,第一时间,分享更多Hadoop干货,欢迎转发和分享。

原创文章,欢迎转载,转载请注明:转载自微信公众号Hadoop实操

原文发布于微信公众号 - Hadoop实操(gh_c4c535955d0f)

原文发表时间:2018-06-08

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏LanceToBigData

Hadoop(十四)MapReduce原理分析

前言   上一篇我们分析了一个MapReduce在执行中的一些细节问题,这一篇分享的是MapReduce并行处理的基本过程和原理。   Mapreduce是一个...

81380
来自专栏Albert陈凯

3.3 Spark存储与I/O

3.3 Spark存储与I/O 前面已经讲过,RDD是按照partition分区划分的,所以RDD可以看作由一些分布在不同节点上的分区组成。由于partiti...

35470
来自专栏LhWorld哥陪你聊算法

【Spark篇】---Spark中Shuffle机制,SparkShuffle和SortShuffle

Spark中Shuffle的机制可以分为HashShuffle,SortShuffle。

24030
来自专栏Spark学习技巧

用java提交一个Spark应用程序

第一种方式 经常有人在公众号留言或者在群里问浪尖,如何使用java代码提交一个Spark应用程序。在这里浪尖介绍一种简单的方法来实现这个功能。 首先用vim打开...

424100
来自专栏Albert陈凯

Spark详解07广播变量BroadcastBroadcast

Broadcast 顾名思义,broadcast 就是将数据从一个节点发送到其他各个节点上去。这样的场景很多,比如 driver 上有一张表,其他节点上运行的 ...

40960
来自专栏FreeBuf

浅谈拒绝服务攻击的原理与防御(3)| 反射DDOS攻击利用代码

0×01 前言 之前发了一篇关于反射DDOS攻击原理以及反射资源扫描的文章,本来今天的这个应该并到那篇文章里,共称为反射DDOS攻击扫描与利用,但是我怕这样做会...

30190
来自专栏Spark学习技巧

必读:Spark与kafka010整合

SparkStreaming与kafka010整合 读本文之前,请先阅读之前文章: 必读:再讲Spark与kafka 0.8.2.1+整合 Spark Str...

82970
来自专栏Albert陈凯

Spark详解01概览|Spark部署|执行原理概览Job 例子

概览 拿到系统后,部署系统是第一件事,那么系统部署成功以后,各个节点都启动了哪些服务? 部署图 ? Spark部署图 从部署图中可以看到 整个集群分为 Mast...

41750
来自专栏racaljk

Erlang Concurrent 并发进阶

使用Erlang而不是其他函数式编程语言的主要原因之一就是Erlang的并发处理能力和分布式编程。并发意味着程序可以在同一时刻执行多个线程。举个例子,操作系统允...

16440
来自专栏小鄧子的技术博客专栏

【译】使用RxJava从多个数据源获取数据

试想,需要一些动态数据的时候,只要每次都请求网络就可以了。但是,更有效率的做法是,把联网得到的数据,缓存到磁盘或内存。

17820

扫码关注云+社区

领取腾讯云代金券