认识wordcount(三)
0. 执行前准备
0.1 配置好的完全分布式环境
高可用环境会有两个master节点,会报错,暂时没去找解决方案!
但是可以在src下的配置文件配置,或者在程序中指定一个master,破坏高可用的两个master情况,但是不会变更整个集群环境,说起来就是暂时配置的一个环境。(修改【fs.defaultFS】【yarn.resourcemanager.hostname】这两个配置。)
如果直接用完全分布式就简单了,直接做就行。
0.2 将HDFS根目录赋予777权限
为了安全应该只给对应目录授权(但是我也没有实操经验,只能说给解决问题的方案,日后改进吧)
0.3 拷贝Hadoop二进制包中的可执行Jar包
将Hadoop二进制包中的可执行Jar包拷贝到工程下新建的lib文件夹,将他们都右键【build path】->【Add to build path】
0.4 配置文件
0.4.1 core-site.xml
<property>
<name>fs.defaultFS</name>
<value>hdfs://192.168.204.110:9000</value>
</property>
#修改namenode的默认存储位置
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/tmp/hadoop-${user.name}</value>
<description>A base for other temporary directories.</description>
</property>
0.4.2 hdfs-site.xml
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/name, /home/hadoop/backup/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/data</value>
</property>
0.4.3 yarn-site.xml
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<description>The hostname of the RM.</description>
<name>yarn.resourcemanager.hostname</name>
<value>192.168.204.110</value>
</property>
0.4.4 mapred-site.xml
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.app-submission.cross-platform</name>
<value>true</value>
</property>
0.5 设置日志配置文件
将Hadoop二进制包中的hadoop-2.7.3\etc\hadoop\log4j.properties文件拷贝到src下,才可以看到执行过程的日志信息
1. 本地eclipse提交到集群
1.1 测试数据
1.1.1 word1.txt
hadoop
hive spark
zookeeper pig flink
hadoop hbase
spark
hdfs
namenode
hadoop sqoop hive hbase
1.1.2 word2.txt
datanode namenode pig hive
spark hbase hadoop
sqoop
zookeeper
mahout
flume
yarn mapreduce
impala storm kafka
1.1.3 word3.txt
hadoop spark
hive
kafka
flume pig flink
zookeeper
1.2 WordCount程序
1.2.1 Mapper
package wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class WordCountMap extends Mapper<LongWritable, Text, Text, IntWritable>{
private Text word = new Text();
private IntWritable one = new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] words = line.split(" ");
for(String str : words) {
word.set(str);
context.write(word, one);
}
}
}
默认的文件读取格式是TextInputFormat(由job.setInputFormat(输入类.class)设定),key为每行的首字符在文件中的字节数,value是一行的文本。
- 将一行文本从TextWritable转为String
- 因为文本中间是空格分隔,所以用空格分解文本
- 遍历获得的String数组,将文本和1组合成<文本,1>的二元组
- 形成中间数据传递给Reducer
1.2.2 Reducer
package wordcount;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class WordCountRecuce extends Reducer<Text, IntWritable, Text, IntWritable>{
private IntWritable _sum = new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values,
Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable value : values) {
sum += value.get();
_sum.set(sum);
}
context.write(key, _sum);
}
}
Mapper阶段结束后,传给Reducer的是一个key和value集合的二元组<key,Iterable>
- 遍历Mapper传过来的IntWritable集合,将相同key值的value统计成总数
- 输出key和总数的二元组<key,_sum>
1.2.3 Driver
package wordcount;
import java.io.IOException;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class WordCountDriver {
public static void main(String[] args) throws ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
try {
Job job = Job.getInstance(conf);
job.setMapperClass(WordCountMap.class);
job.setReducerClass(WordCountRecuce.class);
job.setJobName("wordcount");
job.setJarByClass(WordCountDriver.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true)?0:1);
} catch(IOException e) {
e.printStackTrace();
}
}
}
- 首先,获取一个Configuration对象
- 用Configuration对象获得Job实例
- 设置Job的MapperClass
- 设置Job的ReducerClass
- 设置Job的Name
- 设置打包的主类JarByClass
- 设置Mapper输出的key类型MapOutputKeyClass
- 设置Mapper输出的value类型MapOutputValueClass
- 设置Reducer输出的key类型OutputKeyClass
- 设置Reducer输出的value类型OutputValueClass
- 设置文件输入的路径setInputPaths
- 设置文件输出的路径setOutputPath
- 设置等待Job完成的方法waitForCompletion(必须设置,否则任务根本没有执行)
1.3 打Jar包
只打对应项目的package,其他任何东西都不要,可以在打包时选定加载时的主类,这样在执行时就可以简单一些
1.4 eclipse远程提交运行
1.4.1 拷贝Jar包
将Jar包拷贝到lib下,然后右键该Jar包,【build path】->【Add to build path】
1.4.2 执行
点击运行旁边的小三角形,选择【Run Configurations】,新建一个主类的运行,选择【Arguments】,输入一个输入路径和输出路径【/wordcount /out】,运行。这里是为了调试方便,使用传参的方式提供路径。
1.5 结果(HDFS上)
datanode 1
flink 2
flume 2
hadoop 5
hbase 3
hdfs 1
hive 4
impala 1
kafka 2
mahout 1
mapreduce 1
namenode 2
pig 3
spark 4
sqoop 2
storm 1
yarn 1
zookeeper 3