您现在的位置是:首页 > 文章详情

centOS安装hadoop、编写wordCount小程序

日期:2018-05-08点击:351
#为了方便后续管理,添加hadoop用户,并设置密码 adduser hadoop passwd hadoop #hadoop用户赋权(加sudo可以执行root的操作) #给sudoers文件读写权 chmod u+w /etc/sudoers #赋权 vim /etc/sudoers #在root ALL = (ALL) ALL 下添加 hadoop ALL=(ALL) ALL 并保存 #为了安全撤销写权限 chmod u-w /etc/sudoers 
img_02b7c663f30b475ee77ed2ad94d2c226.png
用户赋权

hadoop依赖1.7+的jdk 如果是3.0+版本的hadoop依赖1.8+的idk,安装jdk

#安装jdk 这边我通过ftp把jdk1.8 tar包传到服务器 #进入相应目录解压 cd /usr/local/tools tar -zxvf jdk-8u171-linux-x64.tar.gz #配置环境变量 sudo vim /etc/profile #文件中添加 JAVA_HOME=/usr/local/tools/jdk1.8.0_171 PATH=$JAVA_HOME/bin:$PATH CLASSPATH=$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar export PATH JAVA_HOME CLASSPATH #保存 source /etc/profile #查看是否安装成功 java -version 
img_1414537a5b21c004c8263798da4b8adc.png
配置jdk

配置SSH

#进入要安装的目录并获取 cd usr/local/tolls wget https://archive.apache.org/dist/hadoop/common/hadoop-2.7.3/hadoop-2.7.3.tar.gz #解压 tar xzvf hadoop-2.7.3.tar.gz #ssh的配置和认证 #测试是否已经可以免密登录 首次的话需点击yes ssh localhost #不可以的话执行以下步骤 #查看是否已安装ssh 出现sshd字样说明已安装 ps -e | grep ssh #如果没有安装 yum install openssh-server #进入 用户的根目录 生成秘钥 ssh-keygen -t rsa #按三次回车 #传到authorized_keys中 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys #测试 如果还是不可以更改下权限$ chmod 600 ~/.ssh/authorized_keys ssh localhost #ssh localhost免密且出现Welcome字样说明ssh配置成功 
img_758df404afb9cc9acc61ccd0c8935985.png
免密登陆

配置haddop环境变量

#类似配置jdk, sudo /etc/profile 添加 并 source /etc/profile 使其立即生效 export HADOOP_HOME=/usr/local/tools/hadoop-2.7.3 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin #检测是否安装配置成功 hadoop version 
img_bbe7b0a264ff21ae1045011e65ee1ff3.png
配置hadoop环境变量
配置hadoopjdk环境 修改hadoop-env.sh
#查看文件 sudo vim /usr/local/tools/hadoop-2.7.3/etc/hadoop/hadoop-env.sh #在最后一行添加 export JAVA_HOME=/usr/local/tools/jdk1.8.0_171 
接下来需要配置四个配置文件(1,2为hdfs相关 3,4为yarn相关,注意备份防止配错)

1.core-site.xml

2.hdfs-site.xml

3.mapred-site.xml

4.yarn-site.xml

img_26cefd788134f0ff6fc87baab9c5233a.png
修改的配置文件
#进入hadoop-2.7.3/etc/hadoop目录 #配置core-site.xml <configuration> <!-- 指定HDFS老大(namenode)的通信地址 --> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> <!-- 指定hadoop运行时产生文件的存储路径 --> <property> <name>hadoop.tmp.dir</name> <value>/usr/hadoop/tmp</value> </property> </configuration> #配置hdfs-site.xml <configuration> <property> <name>dfs.name.dir</name> <value>/usr/hadoop/hdfs/name</value> <description>namenode上存储hdfs名字空间元数据 </description> </property> <property> <name>dfs.data.dir</name> <value>/usr/hadoop/hdfs/data</value> <description>datanode上数据块的物理存储位置</description> </property> <!-- 设置hdfs副本数量 --> <property> <name>dfs.replication</name> <value>1</value> </property> </configuration> #配置mapred-site.xml <configuration> <!-- 通知框架MR使用YARN --> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> </configuration> #配置yarn-site.xm <configuration> <!-- reducer取数据的方式是mapreduce_shuffle --> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> </configuration> 
img_bcb039c3d02fba97badfd38af26456a0.png
详细配置
启动hdfs
cd /usr/local/tools/hadoop-2.7.3 #第一次启动hdfs格式化 也可以进入bin目录直接执行hdfs namenode -format #这边初始化的时候报了java.io.IOException: Cannot create directory /usr/hadoop/hdfs/name/current 的错,原因是hdfs设置存储元数据的地址没有写权限(可能因为不是root用户) #解决方案 赋予写权 sudo chmod -R a+w /usr/hadoop/ ./bin/hdfs namenode -format #启动命令 #初次启动的时候报 /usr/local/tools/hadoop-2.7.3/logs/hadoop-hadoop-secondarynamenode-aliyun-spark.out: No such file or directory的错 这个时候mkdir logs 然后 sudo chmod -R a+w /usr/local/tools/hadoop-2.7.3/logs/ 即可 ./sbin/start-dfs.sh #停止 ./sbin/stop-dfs.sh #在网页打开 localhost:50070测试hdfs是否启动 #查看启动的相关进程 jps 
出现这个界面说明hdfs启动成功
img_5e5bea79867c651550f4ae42eb1f39c3.png
hdfs界面

启动yarn

cd /usr/local/tools/hadoop-2.7.3 #启动yarn ./sbin/start-yarn.sh 【 #启动如果报了hadoop@localhost's password: localhost: Permission denied, please try again.的错 解决方案 #先关闭yarn并修改当前用户密码 sudo passwd hadoop #修改密码后 重新格式化namenode ./bin/hdfs namenode -format #重启ssh之后再启动 sudo service ssh restart 】 #在网页打开 localhost:8088查看yarn是否启动 #关闭yarn ./sbin/stop-yarn.sh 
出现这个界面说明yarn启动成功
img_55981b06ba7edf3a7db0793db7f0e88a.png
yarn界面
如果想一次性启动所有
cd /usr/local/tools/hadoop-2.7.3 ./sbin/start-all.sh 
本地测试worldcount

hadoop安装成功后,先直接使用linux文件系统做测试,不使用hadoop fs相关命令

#在hadoop-2.7.3文件夹中进入 cd share/hadoop/mapreduce/ #查看列表 ls #查看hadoop-mapreduce-examples-2.7.3.jar 中的类 可以看到里面包含worldCount.class jar tvf hadoop-mapreduce-examples-2.7.3.jar #创建准备测试的数据 #在根目录下创建input目录 sudo mkdir -p dataLocal/input/ #赋予写权 sudo chmod -R a+w dataLocal/input/ #进入目录并填充数据 二次填充file2 cd dataLocal/input/ sudo echo "hello world, I am jungle. bye world" > file1.txt sudo echo "hello hadoop. hello jungle. bye hadoop." > file2.txt sudo echo "the great software is hadoop." >> file2.txt #计数file2 #执行前需把input文件传到hdfs #查看hdfs当前文件 hdfs dfs -ls / #创建input文件夹 hadoop fs -mkdir -p /input #本地文件推送到hdfs的input目录下 hdfs dfs -put dataLocal/input/file2.txt /input #如果要计数所有txt文件可 #hdfs dfs -put dataLocal/input/*.txt /input #如果缺省路径默认表示 user/{user_name}下 这边我output缺省默认放在了 /user/hadoop/下 hadoop jar /usr/local/tools/hadoop-2.7.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar wordcount /input output #如果报了There are 0 datanode(s) running and no node(s) are excluded in this operation.的异常,先jps查看datanode进程是否正在运行 且namenode的9000端口(core-site.xml文件中的fs.default.name节点配置,所有的DataNode都要通过这个端口连接NameNode)是否开启,防火墙是否允许 也有可能是两次格式化hadoop 导致没有datenode 解决方案 找到hdfs-site.xml设置的dfs.name.dir的路径/usr/hadoop/hdfs/name 删除下面的current文件夹 之后重新格式化hadoop namenode -format 重启下hdfs和yarn #jps继续查看datenode是否启动 如果仍未启动 可能是因为datanode的clusterID 和 namenode的clusterID(第一次格式化dfs后,启动并使用了hadoop,后来又重新执行了格式化命令(hdfs namenode -format),这时namenode的clusterID会重新生成,而datanode的clusterID 保持不变) 总之就是得让datanode启动 #查看输出的output hadoop dfs -ls ./output #查看内部输出worldcount MapReduce后的结果 hadoop dfs -cat ./output/* hadoop dfs -cat ./output20180509230557/* #删除hdfs文件 假设删除/inputfile1 hadoop dfs -rmr /inputfile1 #如果想计算dataLocal/input/目录下所有文件的wordcount hdfs dfs -put dataLocal/input/*.txt /input 
hadoop fs、hadoop dfs、hdfs dfs区别 hadoop fs:使用面最广,可以操作任何文件系统。 hadoop dfs与hdfs dfs:只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后者。 
本地测试worldcount

hadoop安装成功后,先直接使用linux文件系统做测试,不使用hadoop fs相关命令

#在hadoop-2.7.3文件夹中进入 cd share/hadoop/mapreduce/ #查看列表 ls #查看hadoop-mapreduce-examples-2.7.3.jar 中的类 可以看到里面包含worldCount.class jar tvf hadoop-mapreduce-examples-2.7.3.jar #创建准备测试的数据 #在根目录下创建input目录 sudo mkdir -p dataLocal/input/ #赋予写权 sudo chmod -R a+w dataLocal/input/ #进入目录并填充数据 二次填充file2 cd dataLocal/input/ sudo echo "hello world, I am jungle. bye world" > file1.txt sudo echo "hello hadoop. hello jungle. bye hadoop." > file2.txt sudo echo "the great software is hadoop." >> file2.txt #计数file2 #执行前需把input文件传到hdfs #查看hdfs当前文件 hdfs dfs -ls / #创建input文件夹 hadoop fs -mkdir -p /input #本地文件推送到hdfs的input目录下 hdfs dfs -put dataLocal/input/file2.txt /input #如果要计数所有txt文件可 #hdfs dfs -put dataLocal/input/*.txt /input #如果缺省路径默认表示 user/{user_name}下 这边我output缺省默认放在了 /user/hadoop/下 hadoop jar /usr/local/tools/hadoop-2.7.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar wordcount /input output #如果报了There are 0 datanode(s) running and no node(s) are excluded in this operation.的异常,先jps查看datanode进程是否正在运行 且namenode的9000端口(core-site.xml文件中的fs.default.name节点配置,所有的DataNode都要通过这个端口连接NameNode)是否开启,防火墙是否允许 也有可能是两次格式化hadoop 导致没有datenode 解决方案 找到hdfs-site.xml设置的dfs.name.dir的路径/usr/hadoop/hdfs/name 删除下面的current文件夹 之后重新格式化hadoop namenode -format 重启下hdfs和yarn #jps继续查看datenode是否启动 如果仍未启动 可能是因为datanode的clusterID 和 namenode的clusterID(第一次格式化dfs后,启动并使用了hadoop,后来又重新执行了格式化命令(hdfs namenode -format),这时namenode的clusterID会重新生成,而datanode的clusterID 保持不变) 总之就是得让datanode启动 #查看输出的output hadoop dfs -ls ./output #查看内部输出worldcount MapReduce后的结果 hadoop dfs -cat ./output/* hadoop dfs -cat ./output20180509230557/* #删除hdfs文件 假设删除/inputfile1 hadoop dfs -rmr /inputfile1 #如果想计算dataLocal/input/目录下所有文件的wordcount hdfs dfs -put dataLocal/input/*.txt /input 
hadoop fs、hadoop dfs、hdfs dfs区别 hadoop fs:使用面最广,可以操作任何文件系统。 hadoop dfs与hdfs dfs:只能操作HDFS文件系统相关(包括与Local FS间的操作),前者已经Deprecated,一般使用后者。 

下面用idea编写wordcount程序

1.mac本地运行wordcount(localohost),前提是本机装有hadoop(mac安装步骤与在linux上大致相同)

import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; 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.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; /** * Created by LJW on 2018/5/9. * 本地运行wordCount */ public class WordCount { /** * 用户自定义map函数,对以<key, value>为输入的结果文件进行处理 * Map过程需要继承org.apache.hadoop.mapreduce包中Mapper类,并重写其map方法。 * 通过在map方法中添加两句把key值和value值输出到控制台的代码 * ,可以发现map方法中value值存储的是文本文件中的一行(以回车符为行结束标记),而key值为该行的首字母相对于文本文件的首地址的偏移量。 * 然后StringTokenizer类将每一行拆分成为一个个的单词 * ,并将<word,1>作为map方法的结果输出,其余的工作都交有MapReduce框架处理。 每行数据调用一次 Tokenizer:单词分词器 */ public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{ private final static IntWritable one = new IntWritable(1); private Text word = new Text(); //由于该例子未用到key的参数,所以该处key的类型就简单指定为Object @Override public void map(Object key, Text value, Context context ) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } } } /** * 用户自定义reduce函数,如果有多个热度测,则每个reduce处理自己对应的map结果数据 * Reduce过程需要继承org.apache.hadoop.mapreduce包中Reducer类,并重写其reduce方法。 * Map过程输出<key,values>中key为单个单词,而values是对应单词的计数值所组成的列表,Map的输出就是Reduce的输入, * 所以reduce方法只要遍历values并求和,即可得到某个单词的总次数。 */ public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> { private IntWritable result = new IntWritable(); @Override public void reduce(Text key, Iterable<IntWritable> values, Context context ) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } result.set(sum); context.write(key, result); } } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); try { Job job = Job.getInstance(conf, "word count"); //如果不是本地 使用setJarByClass指定所在class文件 job.setJarByClass(WordCount.class); job.setMapperClass(TokenizerMapper.class); job.setCombinerClass(IntSumReducer.class); job.setReducerClass(IntSumReducer.class); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); //原文件目录 待计算 String path1 = "hdfs://localhost:9000/input"; //正常情况输出路径每次都要删除再通过计算填充 为方便测试每次输出到一个新的路径 String path2 = "hdfs://localhost:9000/output" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); FileInputFormat.addInputPath(job,new Path(path1)); // if(fs.exists(path2)) { // fs.delete(path2, true); // System.out.println("存在此输出路径,已删除!!!"); // } //输出文件目录 计算之后的输出目录 String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); FileOutputFormat.setOutputPath(job, new Path(path2)); job.waitForCompletion(true) ; System.exit(job.waitForCompletion(true) ? 0 : 1); } catch (Exception e) { e.printStackTrace(); } } } 
img_ac428f3f25fdd0f6252844a0d6a5f0a8.png

后续遇到的坑

博主在阿里云hadoop启动了很长一段时间后,发现突然就关闭不了服务了

网上查询可能有以下原因

①hadoop在stop的时候依据的是datanode上的mapred和dfs进程号。而默认的进程号保存在/tmp下,linux默认会每隔一段时间(一般是一个月或者7天左右)去删除这个目录下的文件。因此删掉hadoop-hadoop-jobtracker.pid和hadoop-hadoop-namenode.pid两个文件后,namenode自然就找不到datanode上的这两个进程(最常见)
②环境变量 $HADOOP_PID_DIR 在你启动hadoop后改变了
③用另外的用户身份执行stop-all

目测我的是因为第一个原因,解决方案

①ps -ef | grep java | grep hadoop 查找hadoop的所有相关进程,再次jps查看只剩jps。
②修改$HADOOP_HOME/conf/hadoop-env.sh里边,去掉export HADOOP_PID_DIR=/var/hadoop/pids的#号,创建/var/hadoop/pids或者你自己指定目录

原文链接:https://yq.aliyun.com/articles/651059
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章