学习Hadoop,首先想到的是用虚拟机,但是虚拟机配置繁琐,而且多个节点占用资源也很大,那就用docker吧
在dockerhub上找了一圈,发现这个还不错:
docker pull harisekhon/hadoop:2.9
只是版本最高只有2.9,但是练习应该够了
查看项目可以发现,在根目录下有一个entrypoint.sh
文件,作为入口,如果不传任何参数,就会执行初始化,如果传了参数,就会把这个参数作为命令执行
所以我们创建一个容器
docker run -d IMAGE-ID /entrypoint.sh
容器运行成功后,就可以执行hadoop命令了
docker exec -it CONTAINER-ID /entrypoint.sh hadoop
hadoop streaming藏的比较深/hadoop-2.9.0/share/hadoop/tools/lib/
,所以我们创建一个软链,便于以后操作
ln -s /hadoop-2.9.0/share/hadoop/tools/lib/hadoop-streaming-2.9.0.jar /hadoop-2.9.0/hadoop-streaming.jar
因为我比较熟悉python,所以用python做MapReduce,安装python
yum -y install https://centos7.iuscommunity.org/ius-release.rpm
yum install python36u
将本地的测试文件上传到hadoop中
hadoop fs -mkdir /app/test
hadoop fs -put ./test.txt /app/test
在本地新建一个项目,用MapReduce统计单词个数
mapper.py
#!/usr/bin/python
import sys
for line in sys.stdin:
line = line.strip()
if line != '':
print(line)
reducer.py
#!/usr/bin/python
import sys
result = {}
for line in sys.stdin:
line = line.strip()
if line in result:
result[line] = result[line] + 1
else:
result[line] = 1
for item in result:
print("{}: {}".format(item, result[item]))
在创建一个脚本用来跑任务,run.sh
work_dir=`pwd`
mapper_file="mapper.py"
reducer_file="reducer.py"
mapper="python $mapper_file"
reducer="python $reducer_file"
mapper_src=$work_dir/$mapper_file
reducer_src=$work_dir/$reducer_file
input=/app/test/test.txt
run_time=`date +%Y%m%d%H%M%S`
output=/app/test/$run_time
log_file_name="result.log"
hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-D mapred.job.map.capacity=5000 \
-D mapred.job.reduce.capacity=5000 \
-D stream.num.map.output.key.fields=1 \
-D num.key.fields.for.partition=1 \
-mapper "$mapper" \
-reducer "$reducer" \
-input "$input" \
-output "$output" \
-file "$mapper_src" \
-file "$reducer_src" \
-partitioner org.apache.hadoop.mapred.lib.KeyFieldBasedPartitioner \
[ $? -eq 0 ] && echo "hadoop task succ!" || { echo "hadoop task fail!" ; exit 1; }
hadoop fs -lsr $output
hadoop fs -cat $output/* > $log_file_name
运行成功后,就会把结果保存在当前目录下的result.log文件中
如何构建hadoop集群
首先需要生成一个子网,这样就可以为容器指定静态ip
docker network create --subnet=172.18.0.0/16 mynet123
然后同时运行三个容器,一个master,两个slave
docker run -d --name="master" -h "master" --net mynet123 --ip 172.18.0.2 IMAGE-ID /entrypoint.sh
docker run -d --name="slave1" -h "slave1" --net mynet123 --ip 172.18.0.3 IMAGE-ID /entrypoint.sh
docker run -d --name="slave2" -h "slave2" --net mynet123 --ip 172.18.0.4 IMAGE-ID /entrypoint.sh
修改三个容器中的hosts,以便他们能够用hostname相互访问
# /etc/hosts
172.18.0.2 master
172.18.0.3 slave1
172.18.0.4 slave2
设置免密登录,将master的公钥复制到slave中去
# 在master上运行
ssh-copy-id -i ~/.ssh/id_rsa.pub slave1
ssh-copy-id -i ~/.ssh/id_rsa.pub slave2
在复制过程中需要输入slave机器的root密码,如果不知道需要登录slave,然后用passwd
修改密码即可
将master和slave关联,在master中修改slaves配置,添加slave的hostname
# /hadoop-2.9.0/etc/hadoop/slaves
slave1
slave2
在slave中修改hdfs的地址
# /hadoop-2.9.0/etc/hadoop/core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:8020</value>
</property>
</configuration>
将三台的服务都关闭
/hadoop/sbin/stop-dfs.sh
/hadoop/sbin/stop-yarn.sh
然后只需要在master中启动就可以了
/hadoop/sbin/start-dfs.sh
/hadoop/sbin/start-yarn.sh
可以通过jps
命令查看服务运行情况