Hadoop 环境搭建--全集--超详细
总论, 实验环境
说在前面: 该文章只为记录此次实验总结, 方便以后, 并加深记忆, 超级基础.
- Linux版本: CentOS 7
- hadoop版本: hadoop-2.7.5
- 虚拟机: VMware + xshell
- 集群环境:
主机名称 IP地址 备注 hadoop01 192.168.192.128 master hadoop02 192.168.192.129 slave hadoop03 192.168.192.130 slave - hadoop各结点:
hadoop01 hadoop02 hadoop03 NameNode SecondaryNameNode DataNode DataNode DataNode NodeManager NodeManager NodeManager JobHistoryServer ResourceManager - 文件下载地址:
Win10 hadoop环境变量: hadoop-2.7.5-master:
hadoop.dll: 此文件复制到C盘 Windows/System32 下面: hadoop.dll
hadoop-2.7.5: hadoop-2.7.5
我的hadoop配置文件 hadoop/etc/*: etc - 使用用户 root, hadoop
1. jdk与tomcat安装
1.1. jdk 安装
-
实验目的: 在VMware 上安装 jdk 8
-
实验步骤:
方法一-
一步安装及配置 jdk (仅适用于CentOS)
yum install java-1.8.0-openjdk* -y
截图:
结果测试:
-
配置环境变量:
yum 安装位置: /usr/lib/jvm/java
在 /etc/profile 中添加:#set java environment export JAVA_HOME=/usr/lib/jvm/java export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar export PATH=$PATH:$JAVA_HOME/bin
-
使profile生效
sources /etc/profile
-
结果:
方法二
- 下载jdk压缩包到 /usr/local/src目录
- 解压到 /usr/local/java下面
- 配置环境变量
-
1.2 tomcat 安装 (与jdk安装大致相同)
-
解压下载的tomcat到目录下
tar -xvf [文件名] -C /usr/local
-
给 tomcat 更名, 把长名字改成 tomcat
-
修改tomcat环境变量
Tomcat是需要jdk才能运行,上面解压安装后,还需要在tomcat里配置jdk的目录.
修改tomcat环境变量有三种方法:
第一种:定义在全局里;如果装有多个JDK的话,定义全局会冲突,不建议[root@Tomcat ~]# vim /etc/profile
第二种:写用户家目录下的环境变量文件.bash_profile
第三种:是定义在单个tomcat的启动和关闭程序里,建议使用这种[root@Tomcat ~]# vim /usr/local/tomcat/bin/startup.sh --tomcat的启动程序 [root@Tomcat ~]# vim /usr/local/tomcat/bin/shutdown.sh --tomcat的关闭程
把startup.sh和shutdown.sh这两个脚本里的最前面加上下面一段:
# export JAVA_HOME=/usr/local/java export TOMCAT_HOME=/usr/local/tomcat export CATALINA_HOME=/usr/local/tomcat # export CLASS_PATH=$JAVA_HOME/bin/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tool.jar export PATH=$PATH:/usr/local/java/bin:/usr/local/tomcat/bin
-
启动tomcat
-
Windows查看是否启动成功
如上, tomcat 与jdk配置完毕, 当然你还可以配置tomct环境变量
2. 集群环境的配置
2.1 概述
该实验在VMware下, 配置hadoop集群, 包括主要是进行 网络配置, 使集群间可通信.
主机名称 | IP地址 | 备注 |
---|---|---|
hadoop01 | 192.168.192.128 | master |
hadoop02 | 192.168.192.129 | slave |
hadoop03 | 192.168.192.130 | slave |
2.2 网络配置 (该步骤一般在安装虚拟机时已经完成)
-
全局网络设置
将以下所框的地方的ip改成如下即 192.168.192.* , 或者你想设置的子网网络.
-
修改机器IP地址:
修改配置文件 # vi /etc/sysconfig/network-scripts/ifcfg-ens33
其中 IPADDR 为该机器对应的ip地址
更新网络配置 查看结果
# service network restart
2.3 虚拟机克隆
- 在你需要克隆的机器上右键 ->管理->克隆; 克隆出两台机器构成集群
- 如图所示:
2.4 克隆虚拟机上配置网络(在克隆的两台机器上重复以下操作)
-
重新生成 MAC地址, 因为mac地址为机器唯一标识的硬件地址 不可重复;
-
修改 网络配置文件的 ipaddr
使配置生效 # service network restart
-
设置主机名 然后重启:
-
设置hosts (即ip地址对应的主机名)
hosts文件由3部分组成, 空格分开[ 网络IP地址 ] [ 主机名或域名 ] [ 主机名别名 ]
2.5 结果检验:
# ping hadoop02
# ping hadoop03
# ping baidu.com
能 ping 通
如上, 三台机器的hadoop集群环境搭建成功.
3. 设置免密码登陆
3.1 概述
该实验, 主要为了之后使用方便;
但是, 我在第一次没有设置免密登陆时, 启动hadoop集群输入密码会出现异常, 所以又重新设置了免密登陆~ 就不用输入密码啦
3.2 创建hadoop用户 (在每台机器上重复该操作)
-
创建 hadoop 用户
-
修改用户 hadoop 的权限
用户权限修改在 /etc/sudoers 下面配置, 将 hadoop 的权限修改最高
-
切换到 hadoop
3.3 免密码登陆设置 (在每台机器上重复该操作, 只需两步)
-
生成公钥
ssh-keygen -t rsa
注意, 在此期间输入的密码直接回车, 不然就是 有密登陆了…
-
将公钥拷贝到每台机器
ssh-copy-id hadoop@hadoop02
ssh-copy-id hadoop@hadoop03
-
登陆测试
4. hadoop安装与配置
4.1 概述
前置环境:
- jdk安装配置成功
- 集群配置成功
- 使用 hadoop 用户安装
- 免密登陆设置成功 (非必要)
文件:
- hadoop2.7.5: https://download.csdn.net/download/weixin_40978095/10698863
- hadoop/etc/的配置文件:https://download.csdn.net/download/weixin_40978095/10698973
hadoop01 | hadoop02 | hadoop03 |
---|---|---|
NameNode | SecondaryNameNode | |
DataNode | DataNode | DataNode |
NodeManager | NodeManager | NodeManager |
JobHistoryServer | ||
ResourceManager |
4.2 安装hadoop
-
设置用户对 /usr/local/src 的权限, -R 表示级联设置
sudo chown -R hadoop:hadoop /usr/local/src
可见, 该 文件拥有者 用户由 root 变成了 hadoop
-
给该文件设置为 可执行文件
chmod +x hadoop-2.7.5.tar.gz
可以看到文件由原本的红色变成了绿色, 上图是已经执行过该命令, 所以是绿色 -
给 /usr/local/hadoop 作为安装目录
sudo mkdir hadoop
修改该目录权限:
sudo chown -R hadoop:hadoop hadoop
-
解压
-
配置环境变量
vi /etc/profile
加入以下两行
使配置生效
source /etc/profile查看结果:
4.3 配置hadoop(配置文件最好直接复制再修改,容易打错, 其实这里直接复制就可以了)
etc/文件路径:https://download.csdn.net/download/weixin_40978095/10698973
-
配置Hadoop 编辑 hadoop-env.sh 设置JAVA_HOME
这个地方 JAVA_HOME为你安装jdk的时候的 JAVA_HOME
-
编辑core-site.xml
-
创建tmp、NameNode和DataNode目录
-
编辑hdfs-site.xml,将hadoop03设置为secondary name node。
-
编辑slaves,设置datanode
-
编辑yarn-site.xml,将hadoop02设置为resource manager
-
编辑mapred-site.xml。将hadoop03设置为job history server。
4.4 分发Hadoop
-
在hadoop02、hadoop03创建tmp、nanmenode和datanode目录。
-
在hadoop02、hadoop03创建hadoop安装目录
-
将hadoop01安装目录下文件拷贝到hadoop02、hadoop03。该步需要较长时间
-
格式化namenode
4.4 启动hadoop
- 切换到 root 用户, 关闭三台机器的防火墙.
systemctl stop firewalld.service
- 在hadoop01 启动 dfs
- 在hadoop02 启动 yarn
- 在hadoop03 启动 history server
4.5 结果验证
-
编辑windows的 hosts 设置主机名
-
查看HDFS页面: http://hadoop01:50070
-
查看YARN Web 页面http://hadoop02:8088/cluster
-
测试job, 运行MapReduce程序 wordCount
- 编辑测试文件
vi /opt/data/wc.input
里面随便写单词 - 在HDFS上创建目录并上传wc.input
- 运行wordcount
./yarn jar ../share/hadoop/mapreduce/hadoop-mapreduce-examples-2.6.5.jar wordcount /input/wc.input /output
结果查看:
- 编辑测试文件
4.6 常见问题 (待补充)
- 启动了集群之后,发现hadoop2与hadoop3的DATANODE无法启动,网上查找,发现是因为 /opt/data/tmp/data/current/VERSION中的有个Cluster_ID不相同,
解决方法:- 将那个id改成相同的, 我上学期自学的时候这样弄的, 也成功了.
- …/tmp/所有全部删除,然后重新format namenode(推荐!我这次的解决方案,简单)
5. Windows环境下 运行MapReduce (Intelj Maven)
总览
本章主要介绍在 Intelj下调试 mapreduce 的过程;
在 Eclipse 上运行, 只需要配置了 hadoop.dll + 环境变量 之后添加一个 Eclipse的 hadoop插件 即可直接在hadoop集群上运行, 并且可以在设置了权限后, 直接在Eclipse中对HDFS的文件进行操作(CRUD)
5.1 Windows下配置hadoop环境 (可以先编写好MR程序后再进行)
-
hadoop.dll: 此文件复制到C盘 Windows/System32 下面: hadoop.dll
-
若进行了上述操作之后, 在Intelj 下运行MapReduce 程序仍然会报错, 则将以下文件
Win10 hadoop环境变量: hadoop-2.7.5-master:
(该文件来源于 GitHub, 大家可以自己搜索, 我也忘了我怎么搜到的了)解压到任意盘, 并配置hadoop环境变量
配置环境变量:
创建 HADOOP_HOME
添加到 用户变量/系统变量 的path
完成后重启 Intelj 生效, 可以重启电脑保险… -
在 Intelj 下调试 MapReduce 程序 (Maven)
-
创建一个项目:
File->new->Projec
然后一直下一步, 直到:
-
新建一个Maven 的 Module
File ->Project Structure
创建结果:
最后项目结构如下:
-
修改 pom.xml 的dependencies>修改 pom.xml 的dependencies
<dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-hdfs</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-mapreduce-client-core</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-mapreduce-client-jobclient</artifactId> <version>2.7.5</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
- 编写 MapReduce 的wordCount程序:
Map.class:
Reduce.class:package com.cjp.wc; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; import java.util.StringTokenizer; public class Map extends Mapper<LongWritable, Text, Text, IntWritable> { @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); StringTokenizer st = new StringTokenizer(line); while(st.hasMoreTokens()){ String words = st.nextToken(); context.write(new Text(words), new IntWritable(1)); System.out.println(words); } } }
App.class:package com.cjp.wc; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; public class Reduce extends Reducer<Text,IntWritable,Text,IntWritable> { @Override protected void reduce(Text key, Iterable<IntWritable> iterable, Context context) throws IOException, InterruptedException { //汇总 int sum=0; for (IntWritable i:iterable){ sum=sum+i.get(); } //单词--->数量 context.write(key,new IntWritable(sum)); } }
package com.cjp.wc; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; public class App { private final static Log logger = LogFactory.getLog(App.class); public static void main(String[] args){ Configuration conf=new Configuration(); logger.info("args[0]:"+args[0]); logger.info("args[1]:"+args[1]); String input=args[0]; String output=args[1]; try{ Job job = Job.getInstance(conf, "word count"); job.setJarByClass(App.class); job.setMapperClass(Map.class); job.setReducerClass(Reduce.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); FileInputFormat.addInputPath(job,new Path(input)); FileSystem fs= FileSystem.get(conf); Path op1=new Path(output); if(fs.exists(op1)){ fs.delete(op1, true); System.out.println("存在此输出路径,已删除!!!"); } FileOutputFormat.setOutputPath(job,op1); System.exit(job.waitForCompletion(true)?0:1); }catch (Exception e){ e.printStackTrace(); } } }
- 运行:
- 新建输入文件
- 配置Run->
3.运行结果:
- 新建输入文件
-