WordCount开发及运行
开发MR 程序需要引入新的包,还是通过 maven管理依赖
<dependencies> <dependency> <groupId> org.apache.hadoop </groupId> <artifactId> hadoop-mapreduce-client-jobclient </artifactId> <version> 2.7.4 </version> </dependency> <dependency> <groupId> org.apache.hadoop </groupId> <artifactId> hadoop-common </artifactId> <version> 2.7.4 </version> </dependency> <dependency> <groupId> org.apache.hadoop </groupId> <artifactId> hadoop-hdfs </artifactId> <version> 2.7.4 </version> </dependency> </dependencies>
参照:http://hadoop.apache.org/docs/r2.7.4/hadoop-mapreduce-client/hadoop-mapreduce-client-core/MapReduceTutorial.html
import org.apache.hadoop.conf.Configuration ; import org.apache.hadoop.fs.Path ; import org.apache.hadoop.io.IntWritable ; import org.apache.hadoop.io.LongWritable ; 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 ; import org.apache.hadoop.util.GenericOptionsParser ; import java.io.IOException ; import java.util.StringTokenizer ; /** * Created by chingy on 2017/9/29. */ public class MyWordCount { //Mapper class static class MyMapper extends Mapper<LongWritable , Text , Text , IntWritable> { private final static IntWritable ONE = new IntWritable( 1 ) ; private Text word = new Text() ; @Override protected void map (LongWritable key , Text value , Context context) throws IOException , InterruptedException { // super.map(key, value, context);//参考源码最基本的处理 StringTokenizer itr = new StringTokenizer(value.toString()) ; //默认根据空白符/t/n/r/f进行分割 while (itr.hasMoreTokens()) { word .set(itr.nextToken()) ; //取出每个单词作为map输出的key context.write( word , ONE ) ; //通过上下文输出map的key-value,value以1为计数 } } } //Reducer class static class MyReducer extends Reducer<Text , IntWritable , Text , IntWritable> { private IntWritable result = new IntWritable() ; @Override protected void reduce (Text key , Iterable<IntWritable> values , Context context) throws IOException , InterruptedException { // super.reduce(key, values, context);//参考源码最基本的处理 int sum = 0 ; //用于累加 for (IntWritable value : values) { //循环同key的value组,进行处理 sum += value.get() ; //累加 } result .set(sum) ; //累加结果作为reduce输出的value context.write(key , result ) ; } } //Driver public static void run (String[] args) throws Exception { Configuration conf = new Configuration () ; //获取运行环境下的配置信息 conf.set( "mapred.jar" , "D:/IDEAWorks/hadoopAPI/target/hadoopAPI-1.0-SNAPSHOT.jar" ) ; String[] otherArgs = new GenericOptionsParser(conf , args).getRemainingArgs() ; if (otherArgs. length != 2 ) { System. err .println( "Usage: MyWordCount <in> <out>" ) ; System. exit ( 2 ) ; } //创建Jog,设置配置及Job名称 // Job job = new Job(configuration, "wc");//新版废弃的方法 Job job = Job. getInstance (conf , "WC" ) ; //1·设置Job运行的类 job.setJarByClass(MyWordCount. class ) ; //2·设置Mapper及Reducer job.setMapperClass(MyMapper. class ) ; job.setReducerClass(MyReducer. class ) ; job.setOutputKeyClass(Text. class ) ; job.setOutputValueClass(IntWritable. class ) ; //3·设置输入、输出文件路径 FileInputFormat. addInputPath (job , new Path(args[ 0 ])) ; FileOutputFormat. setOutputPath (job , new Path(args[ 1 ])) ; //4·提交Job,等待运行结果,并在客户端显示运行信息 boolean isSuccess = job.waitForCompletion( true ) ; //结束程序,并返回执行结果 System. exit (isSuccess ? 0 : 1 ) ; } public static void main (String[] args) throws Exception { args = new String[] { "file:///D:/data/taotaomm.txt" , "hdfs://n 1 /remoteUser/mm Result " } ; run (args) ; // 这里手动连接的NN,不知道应该怎么解决--undo } }
解决错误:Operation category WRITE is not supported in state standby
ü 如果连接standby 的 NN 进行操作的话,是只读的。 如果是在集群上提交则会自动尝试主备NN,这里手动提交的,则需要手动指定(或者将集群的配置拷贝出来试试)
ü 顺便说下,默认端口是8020,如果配置的时候不指定端口,则访问的时候,也可以不指定端口,而统一用默认的即可。可以仅仅使用主机名访问
windows本地运行 MR 数据读写 HDFS
1. windows本地要有 hadoop 运行库(注意, windows的 Hadoop 编译需要 Windows SDK 7.1 or Visual Studio 2010以上版本 )
a) (这个是2.7.4 版本的,其他版本可以选择 maven 源码 windows 编译): http://pan.baidu.com/s/1jHVuaxg
b) 在本地FS 创建文件授权的时候除了问题( ExitCodeException exitCode=-1073741515: ),需要安装VC++2010sp1
2. hdfs中创建专门供 windows 访问目录,并授权(目录属主为 windows 当前用户即可)
hdfs dfs -mkdir /remoteUser
hdfs dfs -chown chingy :supergroup /remoteUser
hdfs dfs -ls /
远程创建目录,测试授权是否成功:
@Before public void init () throws Exception { //配置文件 Configuration conf = new Configuration() ; //最小化配置 conf.set( "fs.default.name" , "hdfs://n 1 " ) ; //获取文件系统 hdfs = FileSystem. get (conf) ; }
@Test public void mkdir () throws Exception { Path path = new Path( "/remoteUser/chingy" ) ; if ( hdfs .mkdirs(path)) System. out .println( "create dir success!" ) ; }
3. 在本地项目中导入NativeIO 类源码(重写如下部分代码,注释部分即是,大概 500 多行之后,搜索方法签名应该找得到)
public static boolean access (String path , AccessRight desiredAccess) throws IOException { return true; //return access0(path, desiredAccess.accessRight()); }
由于日志关闭了,没有看到执行过程,需要调整日志级别,才能在本地控制台中打印任务运行日志
日志配置:(修改为INFO 即可打印 job 日志,一般使用 WARN 即可)
log4j.rootLogger = WARN,A1 log4j.appender.A1 = org.apache.log4j.ConsoleAppender log4j.appender.A1.layout = org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n
1 远程提交yarn 运行 MR
上述是本地执行,访问HDFS 只是为了数据的读写(可以仅启动 hdfs ),如果需要远程执行,还需要启动并提交 YARN 上
1) 项目要打成jar 包 ,并通过conf 设置本地 jar 包路径,以便 传输远程执行
2) 需要导入远程的核心配置文件(按照提交job 的重要性排序): mapred-site.xml 、 yarn-site.xml 、 hdfs-site.xml
mapred-site.xml
<configuration> <property> <!-- 提交任务的方式:yarn --> <name> mapreduce.framework.name </name> <value> yarn </value> </property> <property> <!-- 开启跨平台,环境变量会得到自动处理,官方文档:将linux中的$PATH、windows中的%PATH%,统一设置为{{PATH}} --> <name> mapreduce.app-submission.cross-platform </name> <value> true </value> </property> </configuration>
yarn-site.xml
<configuration> <property> <name> yarn.nodemanager.aux-services </name> <value> mapreduce_shuffle </value> </property> <property> <!-- 指出提交任务的RM服务器主机名,其它地址都是该地址的间接引用,网上都是配置的yarn.resourcemanager.address --> <name> yarn.resourcemanager.hostname </name> <value> n1 </value> </property> </configuration>
hdfs-site.xml
<configuration> <property> <!-- 避免操作的文件备份数被重置为默认的3 --> <name> dfs.replication </name> <value> 1 </value> </property> </configuration>
然后需要注意的是:
1
·数据不能读取本地的了,即使是远程主机的本地文件系统,
2
·手动配置 fs.defaultFS(避免忘记改回)