课程回顾:
(1)HDFS Web Console
(2)HDFS 命令操作(hdfs dfs–普通操作命令 hdfs dfsadmin 管理员命令)
(3)IDEA Maven 文件夹的创建。
1、HDFS权限问题
针对用户操作没有权限 permission denied:
(1)修改hdfs-site.xml
去掉权限检查(关闭HDFS服务 stop-all.sh;修改后 重新 Start-all.sh)
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
(2)通过设定用户名字 root
System.setProperty("HADOOP_USER_NAME","root");
(3)通过java的-D参数传递。 HADOOP_USER_NAME=root (命令行的方式)
public static void main(String[] args)
https://www.cnblogs.com/-wangjiannan/p/3626965.html
(4)hdfs dfs -chmod 777 /input
让所有用户访问。
(5)针对HDFS权限问题,有kerberos认证。
Kerberos: The Network Authentication Protocol
https://www.cnblogs.com/wukenaihe/p/3732141.html
2、IDEA Maven工程实现HDFS的文件上传与下载
Maven环境中 只有当 POM文件中所有的依赖包全部变成白色。
(1)HDFS文件上传
查看源码:crtl+鼠标左键
## 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 binaries. ##
step1:
下载:hadoop2.7.3 winutils binary
https://github.com/rucyang/hadoop.dll-and-winutils.exe-for-hadoop2.7.3-on-windows_X64
step2: 配置环境变量 拷贝进入 D:\hadoop-2.7.3\bin文件下。
hadoop.home.dir —bin/winutils.exe
HADOOP_HOME:D:\hadoop-2.7.3,然后再path里面增加 %HADOOP_HOME%\bin
或者:System.setProperty("hadoop.home.dir", "D:\\hadoop-2.7.3");
(2)HDFS文件下载
使用IOUtils 输入路径 输出路径
IOUtils.copyBytes(input,output,1024);
3、HDFS上传与下载原理
(1)上传原理
https://www.processon.com
(2)下载原理
(3)nameNode工作机制:
(4)datanode工作机制:
4、安全模式 safe mode
检查副本率是否满足配置要求。副本率不够的时候,会水平复制,当下次那个挂掉的节点如果又活过来的话,副本数就会超过N了,就超了,系统会自动选一个多余的副本删掉
(1)冗余度:dfs.replication 3.有几个冗余的副本。
hdfs-site.xml
<!--注释配置数据块的冗余度,默认是3-->
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
(2)副本率:数据块实际冗余度(M),HDFS配置的数据块应该具有的冗余度(N),
M/N*100%;
例如:知否知否.avi M=2;HDFS配置的 N=3;
2/3=0.667。要求的副本率为 0.99,系统会水平复制数据块到其他节点。
如果是副本率过高,M=6,N=3,副本率=2;大于0.99.系统会删除多余的数据块。
在安全模式下 无法操作HDFS,因为正在进行副本率的检查工作。
进入或查看安全模式的命令:
hdfs dfsadmin -safemode get/enter/leave/wait
5、快照:是一种备份,默认:HDFS快照是关闭
## 一般不建议使用。 ##
快照的本质:将需要备份的数据放到一个隐藏目录下。
(1)开启和关闭快照:
hdfs dfsadmin -allowSnapshot <snapshotDir>
hdfs dfsadmin -disallowSnapshot
hdfs lsSnapshottableDir
查看开启快照的所有文件夹
(2)创建快照:
需要创建快照的目录 快照目录的名字
hdfs dfs -createSnapshot /folder111 backup_folder111_20190118
快照打出的日志:
Created snapshot /folder111/.snapshot/backup_folder111_20190118
(3)删除快照
hdfs dfs -deleteSnapshot /folder111 backup_folder111_20190118
(4)恢复快照:
hdfs dfs -cp /folder111/.snapshot/backup_folder111_20190118/a.png /folder111
6、回收站:默认HDFS的回收站禁用
(1)回收站的配置:
core-site.xml
fs.trash.interval(时间间隔 分钟)
关闭集群后才能起作用。
(2)本质是剪切:回收站开启之后,会把删除的文件放到一个/user/root/.Trash/Current
(3)回收站回复也就是粘贴的过程。
7、配额:Quota
(1)名称配额
限定HDFS目录下,存放文件(目录)的个数>1,最多存放N-1个。
setQuota–指定名称配额
clrQuota–清除名称配额
例如:
hdfs dfs -mkdir /myquota1
hdfs dfsadmin -setQuota 3 /myquota1
hdfs dfs -put ~/test.txt /myquota1----第1个
hdfs dfs -put ~/students.txt /myquota1--第2个。
hdfs dfs -put ~/students01.txt /myquota1---第3个 无法放。
```
错误:put: The NameSpace quota (directories and files) of directory /myquota1 is exceeded: quota=3 file count=4
(2)空间配额 --必须要大于 默认数据块大小。
setSpaceQuota
clrSpaceQuota
8、HDFS底层原理-RPC
Remote Procedure Call:远程过程调用,调用代码不在本地执行,实现调用者与被调用者之间的连接和通信。
基于Client server,相当于 DFSClient 相当于客户端。Namenode集群相当于Server。
9、HDFS底层原理-代理对象Proxy

(1)代理---明星的经纪人
是一种设计模式,提供了对目标对象的另一种访问方式。通过代理对象访问目标对象。
(2)代理分为静态代理和动态代理。
a、静态代理:接口的定义 实现接口。被代理对象与对象实现相同的接口。
# b、动态代理:接口的定义 不需要实现接口(匿名内部类+反射 invoke) #
10、RPC与Proxy程序示例
针对log4j warn
log4j:WARN No appenders could be found for logger (org.apache.hadoop.metrics2.lib.MutableMetricsFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
可以在src/resource/通过 增加 log4j.properties解决。
RPC代码实例:
客户端:
package day0905.rpc.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import day0905.rpc.server.MyInterface;
public class MyRPCClient {
public static void main(String[] args) throws Exception {
// 使用Hadoop RPC的框架调用Server 端的程序
/*
RPC.getProxy(protocol, 调用的接口
clientVersion, 版本号
addr, RPC Server的地址
conf)
*/
//得到的是Server端部署对象的代理对象
MyInterface proxy = RPC.getProxy(MyInterface.class,
MyInterface.versionID,
new InetSocketAddress("localhost", 7788),
new Configuration());
//使用这个代理对象调用Server的程序
String result = proxy.sayHello("Tom");
System.out.println(result);
}
}
服务端:
package day0905.rpc.server;
import org.apache.hadoop.ipc.VersionedProtocol;
public interface MyInterface extends VersionedProtocol{
//定义一个版本号
//使用版本号来进行签名
public static long versionID = 1;
//定义我们业务方法
public String sayHello(String name);
}
package day0905.rpc.server;
import java.io.IOException;
import org.apache.hadoop.ipc.ProtocolSignature;
public class MyInterfaceImpl implements MyInterface {
@Override
public String sayHello(String name) {
System.out.println("*********调用到了Server 端**********");
return "Hello "+name;
}
@Override
public ProtocolSignature getProtocolSignature(String arg0, long arg1, int arg2) throws IOException {
//通过版本号定义签名信息
return new ProtocolSignature(MyInterface.versionID, null);
}
@Override
public long getProtocolVersion(String arg0, long arg1) throws IOException {
//返回版本号
return MyInterface.versionID;
}
}
package day0905.rpc.server;
import java.io.IOException;
import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.ipc.RPC;
import org.apache.hadoop.ipc.RPC.Server;
public class MyRPCServer {
public static void main(String[] args) throws Exception {
// 利用Hadoop RPC的框架实现RPC Server
//使用RPC Builder来构建
RPC.Builder builder = new RPC.Builder(new Configuration());
//定义Server的参数
builder.setBindAddress("localhost");
builder.setPort(7788);
//部署我们的程序
builder.setProtocol(MyInterface.class); //部署的接口
builder.setInstance(new MyInterfaceImpl()); //指定接口的实现类
// 创建RPC Server
Server server = builder.build();
//启动Server
server.start();
}
}
HDFS上传与下载API的使用:
package com.itstar.hunter.demo01;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
public class HDFSClient {
private FileSystem fs = null;
/**
* 加载配置
* @throws URISyntaxException
* @throws IOException
* @throws InterruptedException
*/
@Before
public void init() throws URISyntaxException, IOException, InterruptedException {
// 1. 加载配置文件
Configuration conf = new Configuration();
// 2. 指定副本个数
conf.set("dfs.replication", "2");
// 3. 指定块大小
conf.set("dfs.blocksize", "64m");
// 4. 构造客户端
fs = FileSystem.get(new URI("hdfs://192.168.100.100:9000/"), conf, "root");
}
/**
* 在hdfs中创建文件夹: hdfs dfs -mkdir /文件名
*/
@Test
public void hdfsMkfir() throws IOException {
// 1.调用方法创建文件夹
fs.mkdirs(new Path("/newDir"));
// 2. 关闭资源
fs.close();
}
/**
* 在hdfs中 移动/修改 文件
*/
@Test
public void hdfsRename() throws IOException {
//1.调用移动并修改
fs.rename(new Path("/hello.txt"), new Path("newDir/file.txt"));
// 2. 关闭资源
fs.close();
}
/**
* 在hdfs中删除文件夹
* hdfs dfs -rm -r /
*/
@Test
public void hdfsRm() throws IllegalArgumentException, IOException {
//fs.delete(new Path("/hunterhenshuai"));
//1.调用删除文件方法 参数1:删除的路径 参数2:是否递归删除
fs.delete(new Path("/hello.txt"), true);
fs.close();
}
/**
* 查询hdfs下制定的目录信息
*/
@Test
public void hdfsLs() throws IOException {
// 1. 调用方法,返回远程迭代器
RemoteIterator<LocatedFileStatus> files = fs.listFiles(new Path("/"),true);
// 2. 取迭代器数据
while (files.hasNext()){
// 3. 拿数据
LocatedFileStatus status = files.next();
System.out.println("文件的路径为:" + status.getPath());
System.out.println("块大小为" + status.getBlockSize());
System.out.println("文件长度为:" + status.getLen());
System.out.println("副本数量为:" + status.getReplication());
System.out.println("块信息为:" + Arrays.toString(status.getBlockLocations()));
System.out.println("===============================");
}
//3.关闭资源
fs.close();
}
/*
* 判断文件还是文件夹
*/
@Test
public void findAtHdfs() throws FileNotFoundException, IllegalArgumentException, IOException {
// 1. 展示文件状态信息
FileStatus[] files = fs.listStatus(new Path("/"));
// 2. 遍历所有文件
for (FileStatus file : files) {
if (file.isFile()) {
//文件
System.out.println("文件----f----" + file.getPath().getName());
} else {
//文件夹
System.out.println("文件----d----" + file.getPath().getName());
}
}
}
}
/**
* 上传文件
*/
@Test
public void test1() {
// 1. 加载配置文件
Configuration conf = new Configuration();
// 2. 指定副本个数
conf.set("dfs.replication", "2");
// 3. 指定块大小
conf.set("dfs.blocksize", "64m");
// 4. 构造客户端
FileSystem fs = null;
try {
fs = FileSystem.get(new URI("hdfs://192.168.100.100:9000/"), conf, "root");
// 5. 上传文件
fs.copyFromLocalFile(new Path("C:/Users/think/Desktop/excel.xlsx"), new Path("/aaaaaa.xlsx"));
fs.close();
} catch (IOException | URISyntaxException | InterruptedException e) {
e.printStackTrace();
}
}
/**
* 下载文件
* @throws URISyntaxException
* @throws IOException
* @throws InterruptedException
*/
@Test
public void test2() throws URISyntaxException, IOException, InterruptedException {
Configuration conf = new Configuration();
conf.set("dfs.replication", "2");
conf.set("dfs.blocksize", "64m");
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.100.100:9000/"), conf, "root");
// 5.hdfs数据下载到windows本地
fs.copyToLocalFile(new Path("/girl.txt"), new Path("C:/Users/think/Desktop/"));
fs.close();
}
public class HdfsIO {
private Configuration conf = null;
FileSystem fs = null;
@Before
public void init() throws URISyntaxException, IOException, InterruptedException {
conf = new Configuration();
fs = FileSystem.get(new URI("hdfs://192.168.100.100:9000/"), conf, "root");
}
/**
* 上传文件
* @throws IOException
*/
@Test
public void putFileToHDFS() throws IOException {
// 1. 获取输入流
FileInputStream inputStream = new FileInputStream(new File("C:/Users/think/Desktop/count/words.txt"));
// 2. 获取输出流
FSDataOutputStream outputStream = fs.create(new Path("/test1"));
// 3. 流的拷贝
IOUtils.copyBytes(inputStream, outputStream, conf);
// 4. 关闭资源
IOUtils.closeStream(inputStream);
IOUtils.closeStream(outputStream);
}
/**
* 文件下载
*/
@Test
public void getFileFromHDFS() throws IOException {
// 1.获取输入流
FSDataInputStream inputStream = fs.open(new Path("/data.xlsx"));
// 2. 获取输出流
FileOutputStream outputStream = new FileOutputStream(new File("C:/Users/think/Desktop/new.txt"));
// 3. 流的拷贝
IOUtils.copyBytes(inputStream, outputStream, conf);
// 4. 关闭资源
IOUtils.closeStream(inputStream);
IOUtils.closeStream(outputStream);
}
}
public class ReadData {
private FileSystem fs = null;
/**
* 加载配置
* @throws URISyntaxException
* @throws IOException
* @throws InterruptedException
*/
@Before
public void init() throws URISyntaxException, IOException, InterruptedException {
// 1. 加载配置文件
Configuration conf = new Configuration();
// 2. 构造客户端
fs = FileSystem.get(new URI("hdfs://192.168.100.100:9000/"), conf, "root");
}
/**
* 读数据方式一
* @throws IOException
*/
@Test
public void testReadData() throws IOException {
FSDataInputStream inputStream = fs.open(new Path("/girl.txt"));
byte[] buff = new byte[1024];
inputStream.read(buff);
System.out.println(new String(buff));
inputStream.close();
fs.close();
}
/**
* 读数据方式二
*/
@Test
public void testReadData2() throws IOException, IllegalArgumentException {
// 1. 拿到文件流
FSDataInputStream inputStream = fs.open(new Path("/girl.txt"));
// 2. 缓冲流
//2.缓冲流
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
// 3. 按行读取
String line = null;
while ((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
// 4. 关闭资源
bufferedReader.close();
inputStream.close();
fs.close();
}
/**
* 读取hdfs中指定偏移量
*/
@Test
public void testRandomRead() throws IOException {
//1.拿到流
FSDataInputStream in = fs.open(new Path("/hello.txt"));
in.seek(14);
byte[] b = new byte[5];
in.read(b);
System.out.println(new String(b));
in.close();
}
/*
* 在hdfs中写数据
*/
@Test
public void testWriteData() throws IllegalArgumentException, IOException {
//1.输出流
FSDataOutputStream out = fs.create(new Path("/love.txt"), false);
//2.输入流
FileInputStream in = new FileInputStream("C:/Users/think/Desktop/lovable.txt");
byte[] buf = new byte[1024];
int read = 0;
while((read = in.read(buf)) != -1) {
out.write(buf, 0, read);
}
in.close();
out.close();
fs.close();
}
/*
* 在hdfs中写数据
*/
@Test
public void testWriteData1() throws IllegalArgumentException, IOException {
//1.创建输出流
FSDataOutputStream out = fs.create(new Path("/feiyan"));
//2.创建输入流
FileInputStream in = new FileInputStream(new File("C:/Users/think/Desktop/lovable.txt"));
//3.写数据
out.write("l want have a girlfriend.".getBytes());
//4.关闭资源
IOUtils.closeStream(out);
fs.close();
}
}