hadoop slaves文件_大数据基础【Task 2】搭建Hadoop集群

任务详情:

  1. 搭建HA的Hadoop集群并验证,3节点(1主2从),理解HA/Federation,并截图记录搭建过程
  2. 阅读Google三大论文,并总结
  3. Hadoop的作用(解决了什么问题)/运行模式/基础组件及架构
  4. 学会阅读HDFS源码,并自己阅读一段HDFS的源码(推荐HDFS上传/下载过程)
  5. Hadoop中各个组件的通信方式,RPC/Http等
  6. 学会写WordCount(Java/Python-Hadoop Streaming),理解分布式/单机运行模式的区别
  7. 理解MapReduce的执行过程
  8. Yarn在Hadoop中的作用

参考资料: Google三大论文

【环境搭建视频】链接:https://pan.baidu.com/s/1TmvPBBMkLah-e_H-UHjuxA 提取码:iagg

集群规划1-省机器:

v2-5c9d9fa54bdf1c23c0c324c29e3f2292_b.jpg

集群规划2-清晰:

v2-0258aef0221f8ba962497f5840365136_b.jpg

1.搭建HA的Hadoop集群并验证,3节点(1主2从)

按照集群规划1进行。

1.1 修改hostname

上一次我们搭建了三个虚拟机,我的三个虚拟机的hostname分别为CP1、CP2、CP5,为了连贯性,我把CP5改成CP3。命令hostname可以查看当前主机名,hostname CP3可以将主机名修改为CP3。如图所示:

v2-e57038ff8218e8289f511b9a50fde6ab_b.jpg

对应的命令是:

//编辑文件
vim /etc/sysconfig/network
//修改主机名是CP3,(注意hostname的大小写)
hostname CP3
//命令行下修改hostname
hostname CP3

此时查看hostname就会变成CP3:

v2-43e09ba6a790d40e0bee20d8d4bd40ab_b.png

1.2 建立hostname和ip的映射关系

这一步是为了部署集群方便。在CP1上修改etc/hosts文件:

//编辑hosts文件
vim /etc/hosts
//建立ip和host的映射关系
192.168.1.12 CP1
192.168.1.11 CP2
192.168.1.14 CP3

emmm,忽略我的ip地址的不连贯吧。

v2-abdb49f2ffabad5f48bf72619ae2db1b_b.jpg

同理在CP2、CP3上重复上述过程,文件内容完全一样。

1.3 关闭防火墙

在hadoop集群中会经常发生 机器和机器之间的交互,为了避免因为防火墙产生的意外故障,因此我们需要将防火墙关闭,过程如下:

# 关闭防火墙
systemctl stop firewalld.service            #停止firewall
systemctl disable firewalld.service        #禁止firewall开机启动
firewall-cmd --state                          ##查看防火墙状态,是否是running

v2-083597ea8de9e6ea1d2542e702c184cb_b.jpg

状态从running变成了not running。

1.4 配置集群SSH免密码登录

首先要在三台机器上配置对本机的ssh免密码登录,然后是配置三台机器之间的ssh免密码登录。

对于CP1、CP2和CP3,都执行如下操作(配置对本机的ssh免密码登录):

//创建密钥,一直点确定到结束,默认将公钥放在/root/.ssh目录下
ssh-keygen -t rsa
//将公钥复制为authorized_keys文件,此时使用ssh连接本机就不需要输入密码了
cd /root/.ssh/
cp id_rsa.pub authorized_keys

然后就可以通过ssh连接了:

v2-8f1414aacf16b7432ec9cb15980cb92b_b.jpg

然后配置三台机器之间的ssh免密码登录,针对CP1,执行如下命令:

//将本机公钥拷贝到指定机器的authorized_keys文件中
ssh-copy-id -i CP2

根据提示依次输入yes和CP2的登录密码即可。然后可以尝试ssh CP2,ssh登录机器CP2:

v2-7236b2418dc6d073fcfb79268089f5a5_b.jpg

对CP3也执行上述操作。同样地,CP2、CP3也要执行上述类似操作。

1.5 hadoop的集群部署

首先要把本地的hadoop压缩包上传到虚拟机,我们上传到usr/local文件夹下,因此执行下列命令:

cd /usr/local
rz

rz是工具包lrzsz上传文件到虚拟机的命令,将hadoop文件上传过去。

sz:将选定的文件发送(send)到本地机器 
rz:运行该命令会弹出一个文件选择窗口,从本地选择文件上传到服务器(receive)

然后解压缩文件,并重命名:

//解压hadoop
tar -zxvf hadoop-2.7.3.tar.gz
//将压缩包删掉(可选)
rm -rf hadoop-2.7.3.tar.gz
//改名为hadoop
mv hadoop-2.7.3 hadoop

首先,确认一下hadoop下有bin和sbin目录:

v2-a9177710d281ecf48ad3845caa38f2c5_b.jpg

(注意,下方的环境变量请配置在~/.bashrc里!!!不然可能会出现我遇到的问题)

配置hadoop相关环境变量:

vi /etc/profile   //改成  vi ~/.bashrc

原来的内容是这样的:

export JAVA_HOME=/usr/local/java/jdk1.8.0_131
export CLASSPATH=$JAVA_HOME/lib/
export PATH=$PATH:$JAVA_HOME/bin

修改后的内容是这样的:

export JAVA_HOME=/usr/local/java/jdk1.8.0_131
export HADOOP_HOME=/usr/local/hadoop
export CLASSPATH=$JAVA_HOME/lib/
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

执行命令使之生效:

source /etc/profile    //改成source ~/.bashrc

分别输入下列命令检查看看java和hadoop有没有问题:

v2-f85a4e88bbd6ae31f130bb2054a666e7_b.png

v2-40c47230b14317d8901837c01bf4c7ae_b.jpg

v2-0d31a3faafd40b7e9c751dd04483f3dd_b.jpg

创建/usr/local/data目录:

cd /usr/local
mkdir data

接下来修改hadoop的配置。首先是core-site.xml,在目录hadoop/etc/hadoop下:

cd hadoop/etc/hadoop
vi core-site.xml

core-site.xml(文件末尾)的修改内容如下:

<configuration>
<property>
    <name>fs.default.name</name>
    <value>hdfs://CP1:9000</value>
</property>
</configuration>

然后是hdfs-site.xml的修改内容:

<configuration>
<property>
  <name>dfs.name.dir</name>
  <value>/usr/local/data/namenode</value>
</property>
<property>
  <name>dfs.data.dir</name>
  <value>/usr/local/data/datanode</value>
</property>
<property>
  <name>dfs.tmp.dir</name>
  <value>/usr/local/data/tmp</value>
</property>
<property>
  <name>dfs.replication</name>
  <value>2</value>
</property>
</configuration>

因为我们的主节点是1个,从节点2个,这里的副本也就设置成2个比较合适。

修改mapred-site.xml。发现目录下只有一个叫mapred-site.xml.template的文件,将其重命名:

mv mapred-site.xml.template mapred-site.xml

然后修改,mapred-site.xml的修改内容:

<configuration>
<property>
  <name>mapreduce.framework.name</name>
  <value>yarn</value>
</property>
</configuration>

修改配置文件yarn-site.xml的内容:

<configuration>
<property>
  <name>yarn.resourcemanager.hostname</name>
  <value>CP1</value>
</property>
<property>
  <name>yarn.nodemanager.aux-services</name>
  <value>mapreduce_shuffle</value>
</property>
</configuration>

设置从节点的位置

//编辑slaves文件
vi slaves
//slaves的内容为(删除默认的localhost):
CP2
CP3

上述操作都是针对CP1的,我们要把CP1的hadoop安装包和配置文件都拷贝过去,然后source配置文件,使其生效,并且在CP2和CP3下的/usr/local目录下建立data目录。

首先cd到local目录下,该目录下有hadoop目录和data目录。

然后以递归的方式将hadoop文件拷贝到CP2的/usr/local目录下:

scp -r hadoop root@CP2:/usr/local

可以把配置文件~/.bashrc也拷贝过去,我选择自己修改。然后在CP2中创建/usr/local/目录下的data目录。

对CP3重复上述拷贝、修改配置文件、使配置生效、创建data目录操作。

接下来格式化NameNode并启动集群

//在CP1上格式化集群
hdfs namenode -format
//在CP1上启动集群
start-dfs.sh

然后出错了:

v2-2aee62eaec9bf85179642f719c73d1ad_b.jpg

网上查了一下,说是还要配置hadoop-env.sh文件的jAVA_HOME,因为hadoop找不到Java。。。明明/etc/profile都已经配置好了的。。。(可能配置~/.bashrc就不会出这个错)

没办法,cd到目录/usr/local/hadoop/etc/hadoop下,修改hadoop-env.sh,把java_home参数改成绝对路径:

cd /usr/local/hadoop/etc/hadoop
vi hadoop-env.sh

// 修改内容
export JAVA_HOME=/usr/local/java/jdk1.8.0_131

同样地,对CP2、CP3执行相同操作。

再次执行命令start-dfs.sh。

如果出现“namenode running as process XXX stop it first”这样的错误,可以先stop-dfs.sh,再start-dfs.sh。(start-all.sh可以看到更多)

可以用jps命令查看启动的情况:

v2-59bc96e2e9e1fb61e6e60cfafe795b75_b.jpg

v2-d74a7b26f6a4e009409e56fe1192433f_b.jpg

v2-a1cde1e43f30dcf9748621bf08b787d4_b.jpg

如果用start-all.sh,再输入jps:

v2-9cd3d924a2dc440298280b8f920d3d42_b.jpg

v2-4034d7912991e359e7364cb3afb9edb3_b.jpg

v2-0264f202cf39914acf0d34164037214c_b.jpg

可以在浏览器网址栏输入:虚拟机ip地址:50070,比如我的是:

192.168.1.12:50070

视频教程里说主机名:50070可以打开,但我的一直打不开。

如果上述网址也打不开,可以尝试下列方法:

vi /etc/selinux/config
//修改
SELINUX=disabled

查看一些信息:

v2-bc8c86eb006519c1f5a59d243cda90a1_b.jpg

可以在Utilities-browse the file system查看自己的文件系统,可以看到现在什么都没有:

v2-c5c9dda457fcc9bd5bedd2539323a1cd_b.jpg

可以尝试上传一个文件。在虚拟机vi hello.txt,写入内容,然后执行:

hdfs dfs -put hello.txt /hello.txt

上传文件。

然后再看上述界面:

v2-4da86a161cf1f107cefa7e69b7e3aab7_b.jpg

就有了文件。

下面来启动yarn集群。

start-yarn.sh
//查看yarn集群启动情况
jps
//在web上查看的网址是http://192.168.1.12:8088

1.6貌似不在任务要求里???。。。偏偏这块花了挺长时间的....

1.6 安装hive

同样地,通过在xshell输入rz命令将hive压缩文件上传到虚拟机的/usr/local文件夹下,然后解压缩,重命名,修改环境变量:

//解压缩
tar -zxvf apache-hive-2.1.1-bin.tar.gz
//重命名
mv apache-hive-2.1.1-bin hive
//修改环境变量
vi ~/.bashrc

修改后的~/.bashrc:

export JAVA_HOME=/usr/local/java/jdk1.8.0_131
export HIVE_HOME=/usr/local/hive
export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:$JAVA_HOME/bin:$HIVE_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

让配置文件生效:

source ~/.bashrc

下面来安装mysql

yum install -y mysql-server

执行上述命令后出现“No package mysql-server available”错误,原因是CentOS7带有MariaDB而不是MySQL,MariaDB和MySQL一样也是开元的数据库,可以使用yum -y install mariadb-server mariadb命令安装。

如果必须要安装MySQL,首先必须添加mysql社区repo通过输入命令:

sudo rpm -Uvh http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm

最后使用像安装MySQL的常规方法一样安装mysql:

yum install mysql mysql-server mysql-libs mysql-server

安装过程中,出现“No more mirrors to try”错误,执行下列命令:

yum clean all
yum makecache

再重新安装。这个移动的网速真的太渣了!

从下午5点到凌晨1点,除去中间吃饭洗澡的时间,大概花了6个小时,就做了这么一点。。。

安装完成之后,启动mysql服务:

service mysqld start

配置进程随着机器启动:

chkconfig mysqld on

安装mysql-connector-java驱动包

yum install -y mysql-connector-java

将mysql connector拷贝到hive的lib包中,这样hive才能用mysql驱动包来连接mysql数据库,作为它的元数据库(可以到/usr/share/java目录下查看文件名)

cp /usr/share/java/mysql-connector-java.jar /usr/local/hive/lib

在mysql上创建hive元数据库,创建hive账号并进行授权。先输入mysql进入mysql,再输入下列命令:

create database if not exists hive_metadata;
grant all privileges on hive_metadata.* to 'hive'@'%' identified by 'hive';
grant all privileges on hive_metadata.* to 'hive'@'localhost' identified by 'hive';
grant all privileges on hive_metadata.* to 'hive'@'CP1' identified by 'hive';
flush privileges;
use hive_metadata;

输入exit退出mysql。

配置hive-site.xml:

首先进入/usr/local/hive/conf目录,重命名文件:

mv hive-default.xml.template hive-site.xml

修改配置文件hive-site.xml的内容。由于文件内容太多,我们将其上传到本地机器,用文本编辑器打开进行编辑:

sz hive-site.xml

会弹出一个文本框,选择一个保存位置即可。

然后修改:

<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://CP1:3306/hive_metadata?createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hive</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>hive</value>
</property>

可以使用查找功能,找到上面的name中的内容,修改value的值。

然后用rz命令上传修改后的文件到虚拟机(注意要先删除虚拟机上的文件rm -rf,否则无法上传成功)。

配置其它文件:

//重命名
mv hive-env.sh.template hive-env.sh
//修改hive-config.sh
vi /usr/local/hive/bin/hive-config.sh
//添加内容
export JAVA_HOME=/usr/local/java/jdk1.8.0_131
export HIVE_HOME=/usr/local/hive
export HADOOP_HOME=/usr/local/hadoop

测试 hive是否安装成功

v2-4e66a9433ab3ef6b4fa1681a219e09b1_b.jpg

第一个错误是因为上述jar包有重复绑定Logger类,删除较旧版本即可。

rm -rf /usr/local/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar

第二个错误是因为没有正常启动Hive 的 Metastore Server服务进程。 执行如下命令:

hive --service metastore &

然后又出错:

v2-b1dfed6bf40710f2443c5c6f07b24668_b.jpg

修改conf/hive-site.xml 中的 “hive.metastore.schema.verification” 值为 false:

  <property>
    <name>hive.metastore.schema.verification</name>
    <value>false</value>
    <description>
      Enforce metastore schema version consistency.
      True: Verify that version information stored in is compatible with one from Hive jars.  Also disable automatic
            schema migration attempt. Users are required to manually migrate schema after Hive upgrade which ensures
            proper metastore schema migration. (Default)
      False: Warn if the version information stored in metastore doesn't match with one from in Hive jars.
    </description>
  </property>

但是还有错:

v2-eae6b6a23b7a6a2a3a7ba1874b80d555_b.jpg

需要 使用 schematool工具初始化hive的 元素,执行:

schematool -initSchema -dbType mysql

居然还有错:

v2-e8eaec5deb763eb92e508387ffdb8912_b.jpg

执行下列步骤:

mkdir tmpdir

将conf/hive-site.xml中的所有的"${system:java.io.tmpdir}"修改为"/usr/local/hive/tmpdir/"。

v2-1d323915340042013e473e85434442a6_b.jpg

终于!!!

v2-611e574192b603e83b02f53ba3a4028e_b.jpg

我们可以尝试一下导入txt文件到hive表。

先退出hive(exit;),在/usr/local目录下新建users.txt,内容如下:

v2-e4e2ac61df6fe688a6ff3150c9450464_b.jpg

然后在hive里依次输入:

create table users(id int, name string);
load data local inpath '/usr/local/users.txt' into table users;
select name from users;

v2-cdf10f9ab46011f03c1dad1a231f1e3e_b.jpg

emmm,不知道为什么,这个问题先留着吧,反正是hive语法的问题,应该不是环境部署的问题。

1.7 安装zookeeper

用rz命令将压缩包上传到虚拟机的/usr/local目录下,然后:

tar -zxvf zookeeper-3.4.10.tar.gz
rm -rf zookeeper-3.4.10.tar.gz
mv zookeeper-3.4.10 zk
//修改配置文件
vi ~/.bashrc
//修改后的内容
export JAVA_HOME=/usr/local/java/jdk1.8.0_131
export HIVE_HOME=/usr/local/hive
export HADOOP_HOME=/usr/local/hadoop
export ZOOKEEPER_HOME=/usr/local/zk
export PATH=$PATH:$JAVA_HOME/bin:$HIVE_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$ZOOKEEPER_HOME/bin
//使配置生效
source ~/.bashrc

配置zoo.cfg

cd zk/conf
mv zoo_sample.cfg zoo.cfg
​
vi zoo.cfg
//修改内容
dataDir=/usr/local/zk/data
//新增,需要3个结点以上,而且是奇数
server.0=CP1:2888:3888
server.1=CP2:2888:3888
server.2=CP3:2888:3888

然后设置zk节点标识

//进入zk目录
cd ..
mkdir data
cd data
vi myid
//myid的内容
0

搭建zk集群,在另外两个节点上按照上述步骤配置ZooKeeper,使用scp将zk和.bashrc拷贝到CP2和CP3上即可。

唯一的区别是CP2和CP3上的标识号分别设置为1和2。

//进入local
cd ..
scp -r zk root@CP2:/usr/local
scp ~/.bashrc root@CP2:~/

拷贝之后,去CP2检查一下有没有拷贝成功,并且source配置文件,将myid的内容改成1

v2-54c0f27cf6ab944ecee62fcf52211220_b.jpg

v2-5eefc7aec07b476619d2203064415c35_b.jpg

针对CP3重复上述拷贝、检查、source、修改myid为2的操作。

启动ZooKeeper集群

分别在三台机器上执行:zkServer.sh start

检查ZooKeeper状态:zkServer.sh status

v2-63c107c5ac7afea059915993d7b60322_b.jpg

v2-ec2f9eb531a4def69a1a215008db37aa_b.jpg

v2-4d64185296810437ad093b9d6965a8bd_b.jpg

然后用jps在三个机器上看看三个节点是否都有QuorumPeerMain进程:

v2-ffe013c0950682d2fa5a7d480d1908c5_b.jpg

v2-1d6844cab17f950567b467a2f705dcf7_b.jpg

v2-767d340bea02b8de266784a20e8e5be7_b.jpg

第一部分所有环境搭建的参考资料:

https://blog.csdn.net/zxz547388910/article/details/86468925

https://blog.csdn.net/LoveCarpenter/article/details/78808135

CentOS 7 打开关闭FirewallD防火墙端口命令

https://blog.csdn.net/gongchenupc/article/details/68066990

Hive环境搭建

https://www.cnblogs.com/aspirant/p/6616575.html

2. Google三大论文

看这篇文章吧,写的很好,由于知识储备量不够,暂时无法以自己的语言解释。。。:

https://blog.csdn.net/w1573007/article/details/52966742

3. Hadoop的作用(解决了什么问题)/运行模式/基础组件及架构

Hadoop是一个开源框架,可编写和运行分布式应用处理大规模数据。 Hadoop框架的核心是HDFS和MapReduce。其中 HDFS 是分布式文件系统,MapReduce 是分布式数据处理模型和执行环境。

随着数据的来源途径越来越多,数据的格式也越来越复杂,数据量越来越大,传统的数据库已经很难满足需求,Hadoop就是为了解决这个问题而诞生的。其底层的分布式文件系统具有高拓展性,通过数据冗余保证数据不丢失和提交计算效率,同时可以存储各种格式的数据。同时其还支持多种计算框架,既可以进行离线计算也可以进行在线实时计算。

Hadoop有三种运行模式:单机模式、伪分布式模式、完全分布式模式。

单机模式

  • -默认模式。
  • -不对配置文件进行修改。
  • -使用本地文件系统,而不是分布式文件系统。
  • -Hadoop不会启动NameNode、DataNode、JobTracker、TaskTracker等守护进程,Map()和Reduce()任务作为同一个进程的不同部分来执行的。
  • -用于对MapReduce程序的逻辑进行调试,确保程序的正确。

伪分布式模式

  • -在一台主机模拟多主机。
  • -Hadoop启动NameNode、DataNode、JobTracker、TaskTracker这些守护进程都在同一台机器上运行,是相互独立的Java进程。
  • -在这种模式下,Hadoop使用的是分布式文件系统,各个作业也是由JobTraker服务,来管理的独立进程。在单机模式之上增加了代码调试功能,允许检查内存使用情况,HDFS输入输出,以及其他的守护进程交互。类似于完全分布式模式,因此,这种模式常用来开发测试Hadoop程序的执行是否正确。
  • -修改3个配置文件:core-site.xml(Hadoop集群的特性,作用于全部进程及客户端)、hdfs-site.xml(配置HDFS集群的工作属性)、mapred-site.xml(配置MapReduce集群的属性)
  • -格式化文件系统

完全分布式模式

  • -Hadoop的守护进程运行在由多台主机搭建的集群上,是真正的生产环境。
  • -在所有的主机上安装JDK和Hadoop,组成相互连通的网络。
  • -在主机间设置SSH免密码登录,把各从节点生成的公钥添加到主节点的信任列表。
  • -修改3个配置文件:core-site.xml、hdfs-site.xml、mapred-site.xml,指定NameNode和JobTraker的位置和端口,设置文件的副本等参数

三种模式的集群必须配置信息:

v2-b4968fcb1a45c08a9b65a63b015c78cc_b.jpg

Hadoop的基础组件

Hadoop1.0的核心由HDFS(Hadoop Distributed File System)和MapReduce(分布式计算框架)构成。而在Hadoop2.0中增加了Yarn(Yet Another Resource Negotiator),来负责集群资源的统一管理和调度。

v2-01436f89345a8d99a978ad2bd4ad184e_b.jpg

参考资料:

https://www.zybuluo.com/Cesar/note/239412

https://blog.csdn.net/u010270403/article/details/51493191

https://blog.csdn.net/u013063153/article/details/53115216

https://blog.csdn.net/qq_26442553/article/details/78710170

4.学会阅读HDFS源码,并自己阅读一段HDFS的源码(推荐HDFS上传/下载过程)

源码可以在官网下载,我就直接在网上找了相关的文章看啦,参考下方的资料,讲的很详细了。

以文件上传为例,其执行过程是这样的:

  1. FileSystem初始化,Client拿到NameNodeRpcServer代理对象,建立与NameNode的RPC通信
  2. 调用FileSystem的create()方法,由于实现类为DistributedFileSystem,所以是调用该类中的create()方法
  3. DistributedFileSystem持有DFSClient的引用,继续调用DFSClient中的create()方法
  4. DFSOutputStream提供的静态newStreamForCreate()方法中调用NameNodeRpcServer服务端的create()方法并创建DFSOutputStream输出流对象返回
  5. 通过hadoop提供的IOUtil工具类将输出流输出到本地

下面针对这个执行过程来分析源码。

1.FileSystem初始化,Client拿到NameNodeRpcServer代理对象,建立与NameNode的RPC通信(详情见参考文献第一篇)

2.调用FileSystem的create()方法,由于实现类为DistributedFileSystem,所以是调用该类中的create()方法

HDFSDemo.java
OutputStream os = fs.create(new Path("/test.log"));

这里调用了FileSystem的create()方法,由于FileSystem是一个抽象类,这里实际上是调用的是该类的子类create()方法

//FileSystem.java
 public abstract FSDataOutputStream create(Path f,
       FsPermission permission,
       boolean overwrite,
       int bufferSize,
       short replication,
       long blockSize,
       Progressable progress) throws IOException;

FileSystem.get()返回的是DistributedFileSystem对象,所以这里我们直接进入DistributedFileSystem

//DistributedFileSystem.java
 @Override
   public FSDataOutputStream create(final Path f, final FsPermission permission,
     final EnumSet<CreateFlag> cflags, final int bufferSize,
     final short replication, final long blockSize, final Progressable progress,
     final ChecksumOpt checksumOpt) throws IOException {
     statistics.incrementWriteOps(1);
     Path absF = fixRelativePart(f);
     return new FileSystemLinkResolver<FSDataOutputStream>() {
       @Override
       public FSDataOutputStream doCall(final Path p)
           throws IOException, UnresolvedLinkException {
         final DFSOutputStream dfsos = dfs.create(getPathName(p), permission,
                 cflags, replication, blockSize, progress, bufferSize,
                 checksumOpt);
         //dfs为DistributedFileSystem所持有的DFSClient对象,这里调用DFSClient中的create()方法
         return dfs.createWrappedOutputStream(dfsos, statistics);
       }
       @Override
       public FSDataOutputStream next(final FileSystem fs, final Path p)
           throws IOException {
         return fs.create(p, permission, cflags, bufferSize,
             replication, blockSize, progress, checksumOpt);
       }
     }.resolve(this, absF);
   }

3.DistributedFileSystem持有DFSClient的引用,继续调用DFSClient中的create()方法

DFSClient的create()返回一个DFSOutputStream对象

//DFSClient.java
 public DFSOutputStream create(String src,
                              FsPermission permission,
                              EnumSet<CreateFlag> flag,
                              boolean createParent,
                              short replication,
                              long blockSize,
                              Progressable progress,
                              int buffersize,
                              ChecksumOpt checksumOpt,
                              InetSocketAddress[] favoredNodes) throws IOException {
     checkOpen();
     if (permission == null) {
       permission = FsPermission.getFileDefault();
     }
     FsPermission masked = permission.applyUMask(dfsClientConf.uMask);
     if(LOG.isDebugEnabled()) {
       LOG.debug(src + ": masked=" + masked);
     }
     //调用DFSOutputStream的静态方法newStreamForCreate,返回输出流
     final DFSOutputStream result = DFSOutputStream.newStreamForCreate(this,
         src, masked, flag, createParent, replication, blockSize, progress,
         buffersize, dfsClientConf.createChecksum(checksumOpt),
         getFavoredNodesStr(favoredNodes));
     beginFileLease(result.getFileId(), result);
     return result;
   }

4.DFSOutputStream提供的静态newStreamForCreate()方法中调用NameNodeRpcServer服务端的create()并创建DFSOutputStream输出流对象返回

newStreamForCreate()中的业务逻辑:

//DFSOutputStream.java
  static DFSOutputStream newStreamForCreate(DFSClient dfsClient, String src,
       FsPermission masked, EnumSet<CreateFlag> flag, boolean createParent,
       short replication, long blockSize, Progressable progress, int buffersize,
       DataChecksum checksum, String[] favoredNodes) throws IOException {
     TraceScope scope =
         dfsClient.getPathTraceScope("newStreamForCreate", src);
     try {
       HdfsFileStatus stat = null;
       boolean shouldRetry = true;
       int retryCount = CREATE_RETRY_COUNT;
       while (shouldRetry) {
         shouldRetry = false;
         try {
           //这里通过dfsClient的NameNode代理对象调用NameNodeRpcServer中实现的create()方法
           stat = dfsClient.namenode.create(src, masked, dfsClient.clientName,
               new EnumSetWritable<CreateFlag>(flag), createParent, replication,
               blockSize, SUPPORTED_CRYPTO_VERSIONS);
           break;
         } catch (RemoteException re) {
           IOException e = re.unwrapRemoteException(
               AccessControlException.class,
               DSQuotaExceededException.class,
               FileAlreadyExistsException.class,
               FileNotFoundException.class,
               ParentNotDirectoryException.class,
               NSQuotaExceededException.class,
               RetryStartFileException.class,
               SafeModeException.class,
               UnresolvedPathException.class,
               SnapshotAccessControlException.class,
               UnknownCryptoProtocolVersionException.class);
           if (e instanceof RetryStartFileException) {
             if (retryCount > 0) {
               shouldRetry = true;
               retryCount--;
             } else {
               throw new IOException("Too many retries because of encryption" +
                   " zone operations", e);
             }
           } else {
             throw e;
           }
         }
       }
       Preconditions.checkNotNull(stat, "HdfsFileStatus should not be null!");
      //new输出流对象
       final DFSOutputStream out = new DFSOutputStream(dfsClient, src, stat,
           flag, progress, checksum, favoredNodes);
       out.start();//调用内部类DataStreamer的start()方法,DataStreamer继承Thread,所以说这是一个线程,从NameNode中申请新的block信息;
                
       return out;
     } finally {
       scope.close();
     }
   }

到此,Client拿到了服务端的输出流对象,那么后面就容易了,都是一些简单的文件输出,输入流的操作(hadoop提供的IOUitl)。

参考 资料:

Hadoop之HDFS原理及文件上传下载源码分析(上)

Hadoop之HDFS原理及文件上传下载源码分析(下)

5.Hadoop中各个组件的通信方式,RPC/Http等

RPC,即Remote Procdure Call,中文名:远程过程调用

  (1)它允许一台计算机程序远程调用另外一台计算机的子程序,而不用去关心底层的网络通信细节,对我们来说是透明的。因此,它经常用于分布式网络通信中。

RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。

  (2)Hadoop的进程间交互都是通过RPC来进行的,比如Namenode与Datanode之间,Jobtracker与Tasktracker之间等。

详细的内容可以看下面两篇文章:

https://www.cnblogs.com/nucdy/p/5655811.html

https://www.cnblogs.com/edisonchou/p/4285817.html

6.学会写WordCount(Java/Python-Hadoop Streaming),理解分布式/单机运行模式的区别

另起了一篇文章MapReduce任务—WordCount(Python-Hadoop Streaming)实例

7.理解MapReduce的执行过程

参考资料:

https://zhuanlan.zhihu.com/p/45305945

https://blog.csdn.net/u013087513/article/details/77771600

8.Yarn在Hadoop中的作用

Yarn是Hadoop集群的资源管理系统。Yarn可以提高资源的利用率。Yarn的另一个目标就是拓展Hadoop,使得它不仅仅可以支持MapReduce计算,还能很方便的管理诸如Hive、Hbase、Pig、Spark/Shark等应用。这种新的架构设计能够使得各种类型的应用运行在Hadoop上面,并通过Yarn从系统层面进行统一的管理,也就是说,有了Yarn,各种应用就可以互不干扰的运行在同一个Hadoop系统中,共享整个集群资源

参考资料:

https://blog.csdn.net/suifeng3051/article/details/49486927

https://www.zhihu.com/question/34016617

附:HDFS的常用命令:

HDFS常用Shell命令和基础开发

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值