






























core-site.xml
<!-- 主节点 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://node4:8020</value>
</property>
<!-- obs桶的配置 -->
<property>
<name>fs.obs.access.key</name>
<value>***</value>
</property>
<property>
<name>fs.obs.secret.key</name>
<value>***</value>
</property>
<property>
<name>fs.obs.endpoint</name>
<value>obs.cn-north-4.myhuaweicloud.com</value>
</property>
hdfs-site.xml
<!-- secondaryNamenode配置 -->
<configuration>
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>node4:50090</value>
</property>
<property>
<name>dfs.namenode.secondary.https-address</name>
<value>node4:50091</value>
</property>
</configuration>
yarn-site.xml
<!-- resourcemanger 配置 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node4</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://node4:19888/jobhistory/logs</value>
</property>
mapred-site.xml
<!-- mapreduce配置 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>node4:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node4:19888</value>
</property>
slaves (从节点配置)
其他 hosts 或者免密登录等配置文件省略
主节点输入hadoop namenode -format格式化, 然后输入 start-all.sh 启动 hadoop, 使用 JPS 查看当前 java 进程, 根据上述配置应该有如下显示
主节点:

从节点:

各进程含义:
edit logs和fsimage文件, 帮助恢复 NameNode浏览器访问主节点 50070 端口, 查看 hadoop 网页页面

先声明路径
主函数调用如下, 调用流程: 查看 -> 上传 -> 创建 -> 下载 -> 查看 -> 删除 -> 查看
public static void main(String[] args) {
ExeHDFS testHDFS = new ExeHDFS();
try {
testHDFS.testView();
testHDFS.testUpload();
testHDFS.testCreate();
testHDFS.testDownload();
testHDFS.testView();
testHDFS.testDelete();
testHDFS.testView();
} catch (Exception e) {
e.printStackTrace();
}
}
查看的代码:
// 查看HDFS文件系统
public void testView() throws IOException, URISyntaxException, InterruptedException {
System.out.println("View file:");
Configuration conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://124.70.20.31:8020");
FileSystem hdfs = FileSystem.get(new URI("hdfs://124.70.20.31"), conf, "root");
Path path = new Path(hdfsPath);
FileStatus[] list = hdfs.listStatus(path);
if (list.length == 0) {
System.out.println("HDFS is empty.");
} else {
for (FileStatus f : list) {
System.out.printf("name: %s, folder: %s, size: %s\n", f.getPath(), f.isDirectory(), f.getLen());
}
}
hdfs.close();
}
上传的代码:
// 上传本地文件到HDFS
public void testUpload() throws IOException, URISyntaxException, InterruptedException {
System.out.println("Upload file:");
Configuration conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://124.70.20.31:8020");
FileSystem hdfs = FileSystem.get(new URI("hdfs://124.70.20.31"), conf, "root");
InputStream in = Files.newInputStream(Paths.get("./exp1/src/main/resources/upload.txt"));
OutputStream out = hdfs.create(new Path(hdfsPath + "upload_gcx_2021211184.txt"));
IOUtils.copyBytes(in, out, conf);
System.out.println("Upload successfully!");
hdfs.close();
in.close();
out.close();
}

创建的代码:
// 创建HDFS文件
public void testCreate() throws Exception {
System.out.println("Write file:");
Configuration conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://124.70.20.31:8020");
// 待写入文件内容
// 写入自己姓名与学号
byte[] buff = "Hello world! My name is 郭晨旭, my student id is 2021211184.".getBytes();
// FileSystem 为 HDFS 的 API, 通过此调用 HDFS
FileSystem hdfs = FileSystem.get(new URI("hdfs://124.70.20.31"), conf, "root");
// 文件目标路径,应填写 hdfs 文件路径
Path dst = new Path(hdfsPath + "gcx_2021211184.txt");
try (FSDataOutputStream outputStream = hdfs.create(dst)) {
// 写入文件
outputStream.write(buff, 0, buff.length);
} catch (Exception e) {
e.printStackTrace();
}
// 检查文件写入情况
FileStatus[] files = hdfs.listStatus(dst);
for (FileStatus file : files) {
// 打印写入文件路径及名称
System.out.println(file.getPath());
}
hdfs.close();
}

下载的代码:
// 从HDFS下载文件到本地
public void testDownload() throws IOException, URISyntaxException, InterruptedException {
System.out.println("Download file:");
Configuration conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://124.70.20.31:8020");
FileSystem hdfs = FileSystem.get(new URI("hdfs://124.70.20.31"), conf, "root");
InputStream in = hdfs.open(new Path(hdfsPath + "gcx_2021211184.txt"));
OutputStream out = Files.newOutputStream(Paths.get("./exp1/src/main/resources/download_gcx_2021211184.txt"));
IOUtils.copyBytes(in, out, conf);
System.out.println("Download successfully!");
hdfs.close();
in.close();
out.close();
}

删除的代码:
// 从hdfs删除文件
public void testDelete() throws URISyntaxException, IOException, InterruptedException {
System.out.println("Delete file:");
Configuration conf = new Configuration();
conf.set("dfs.client.use.datanode.hostname", "true");
conf.set("fs.defaultFS", "hdfs://124.70.20.31:8020");
FileSystem hdfs = FileSystem.get(new URI("hdfs://124.70.20.31"), conf, "root");
System.out.println(hdfsPath + "gcx_2021211184.txt");
boolean delete = hdfs.delete(new Path(hdfsPath + "gcx_2021211184.txt"), true);
if (delete) {
System.out.println("Delete successfully!");
} else {
System.out.println("Delete failed!");
}
System.out.println(hdfsPath + "upload_gcx_2021211184.txt");
delete = hdfs.delete(new Path(hdfsPath + "upload_gcx_2021211184.txt"), true);
if (delete) {
System.out.println("Delete successfully!");
} else {
System.out.println("Delete failed!");
}
hdfs.close();
}

整体流程的控制台输出效果:

jdk 的解压问题
提供的 8u292b10 版 jdk 的压缩包需要在 linux 环境下解压,如果在 windows 下解压然后 scp 到服务器上,会丢失部分设置信息导致后期运行 start-all.sh 会丢失 NodeManager 等进程
云防火墙问题
需要去华为的云防火墙打开 50091 端口,让 datanode 可以被外部 PC 机访问
hadoop namenode -format 问题
如果运行 hadoop namenode -format 后出现问题,打算第二次运行本条指令,需要删除 tmp 文件夹下所有 dfs 文件,否则会丢失 datanode 进程
hosts 编辑问题
/etc/hosts 需要注释掉本地环回 ip,否则 datanode 只能被 127.0.0.1 访问到
HDFS 的写入:

HDFS 的读取:

由上述内容分析可得, 常见的出错情况有 NameNode 节点出错、DataNode 节点出错 和 数据出错 这三种情况.
HDFS 中所有元数据都保存在 NameNode 上, NameNode 节点维护 edits 和 fsimage 这两个文件, Hadoop 中提供了两个机制,来确保 NameNode 的安全:
每个 DataNode 周期性地向 NameNode 发送心跳信号, NameNode 通过心跳信号来检测 DataNode 是否存活.
数据块需要重新复制的情况:
DataNode 获取的数据块, 有可能本身就是损坏的, 此时 HDFS 使用 校验和 来判断数据块是否损坏, 如果损坏则从其他副本中读取数据.
SecondaryNameNode 本质上就是记录 checkpoint, 使 NameNode 下次启动时直接从记录的 checkpoint 开始启动

此次实验中我们部署的 HDFS 架构:

HA 架构, 也就是上述容错机制中的增加一个备用 NameNode, 并使用 FailoverController 检测 NameNode 的活跃状态, 主备架构相同
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。