首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小项目:WordCount

小项目:WordCount

作者头像
可爱见见
发布2019-09-09 16:10:29
4210
发布2019-09-09 16:10:29
举报
文章被收录于专栏:卡尼慕卡尼慕

今天可算是完成了一个小项目,虽然看起来很简单,但麻雀虽小,五脏俱全,这个小项目也就是把整个框架的建构与测试走一遍。具体的话包括:服务器上建立测试文件,在Windows下写代码,Win下测试,上传服务器,在服务器上测试。

一路上真的遇到了很多坑,包括环境配置和一些代码问题,更主要的是eclipse本地连接hdfs产生了比较多报错。这两天也一直在查资料,看了很多的博客才解决,总之,解决了就是好事,希望你们能少走一点弯路

服务器上传文件

在服务器上打开Hadoop-2.7.3路径,直接在hadoop根目录下新建一个文本文件。

[songjian@learn hadoop-2.7.3]$ vi 1.txt

在文本文件中随便输入什么单词。这里就直接放图片了。

那么接下来就是上传,直接在Linux命令行敲代码就行。

[songjian@learn hadoop-2.7.3]$ bin/hdfs dfs -put 2.txt /

检查一下,打开hdfs://192.168.6.129:50070。没凑,已经上传成功了。

环境配置

那么整个项目下来比较麻烦的就是环境了,装了很多之前没有搞好的东西才能完成,接下来一步一步做好,别漏了,否则你也要搞很久。

首先,把你在服务器上的hadoop-2.7.3整个文件夹通过FileZila传到本地(这里的话一定要把基本的软件安装好,例如FileZila,SecureCRT),记得放在一个比较好的地方,因为以后会用。我放在了D盘,新建了一个文件夹BigData里面,如图:

以后可以把有关于BigData的东西丢在这个文件夹里面,方便管理。

然后配置hadoop环境变量,这个就跟配置JAVA环境变量一样。我这里就直接放图片了,具体的可以参考一下csdn,很多讲解。

当你这两步都完成以后,可以检查一下自己是否配置完成。打开cmd,输入hadoop,如果出现一下画面即是成功配置!

但是!注意了哈!一开始肯定是不行的,你肯定肯定会遇到一个问题!!!看下图!

1号坑:

Error: JAVA_HOME is incorrectly set.

解决方式:

1、首先检查你的JAVA配置有没有问题!在cmd上输入java -version,若出现下图则说明没问题

2、如果没有出现的话,自己去百度查怎么完成java的环境配置。如果你的JAVA配置没有问题的话,请看第3步。

3、在刚刚放好的hadoop路径中找到这个文件:hadoop-2.7.3\etc\hadoop\hadoop-env.cmd(你的文件在哪就去哪找)。打开文件编辑(这里的话推荐使用NotePad++,因为这个也可以直接连接服务器,很方便)。

这里把自己配置好的JAVA路径改一下,JAVA路径可以在环境变量中找到,如下图:

那么复制下来黏贴就能解决吗?没那么简单!!

注意:因为Program Files中存在空格,所以出现错误。因此,PROGRA~1代替Program Files即可。可以看看前两张图。改完就可以了!

下一步:eclipse连接Hadoop

1、安装Myeclipse(这个就不说了),具体的百度csdn去查,不难。

2、将hadoop-eclipse-plugin-2.6.0.jar(这个jar百度下应该是有的)这个jar放在Myeclipse的安装目录的plugins,如图:

3、在Windows解压hadoop-2.5.0.tar.gz,然后配置hadoop的环境变量(贴两个图上来,就不具体说了,这不就跟配置jdk是一样的嘛~),这个前面刚刚搞定了。

4、打开Myeclipse,请看!

这里点击下面的Map/Reduce Location,在下面的空白处点击右键,添加新的Location。

填好以后,点击小象按右键,Reconnect。成功连接以后就会出现下图!

好,到这里!!!坑来了。

2号坑:

点击tmp,可能会遇到下面这段话:

Permission denied: user=lenvol, access=WRITE_EXECUTE, inode="/input":hadoop:supergroup:rwxr-xr-x。

解决方式:

这个情况是Hadoop权限控制问题。要调整一下权限。

在hadoop的 hdfs-site.xml 配置文件中取消权限校验,即加入以下配置:

<property> <name>dfs.permissions</name> <value>false</value> </property>

如下图:

配置好这些东西,要记得重启服务器,在尝试重新连接。连接成功后就可以打代码啦!

最最最后配置的就是maven,用于管理jar包,特别方便,这个自己下载就好,常规,没有什么坑。

搞完了以后,就可以开始写代码啦!!!

代码

这边的话直接上代码,具体的学习内容出门右拐大数据去学习去!

package com.songjian.learn.mapreduce;



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.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;


public class MyMapReduce {

    //1、自己的map类
    //继承Mapper类,<KEYIN, VALUEIN, KEYOUT, VALUEOUT>   输入的key,输入的value,输出的key,输出的value
    public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable>{
        //创建一个IntWritable类型的对象,给定值为1
        IntWritable i = new IntWritable(1);
        Text keystr  = new Text();
        @Override
        protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
                throws IOException, InterruptedException {
            // TODO Auto-generated method stub
            String line = value.toString();
            //传入每一个map方法的key和value做打印
            System.out.println("key : "+key.get()+"--------- value : "+line);
            String [] strs = line.split(" ");
            for (String str : strs) {
                //每一次循环遍历到一个单词就要输出到下一个步骤
                keystr.set(str);
                System.out.println("map的输出:key : ("+str+",1)");
                context.write(keystr, i);
            }

    /*      StringTokenizer itr = new StringTokenizer(value.toString());
                while (itr.hasMoreTokens()) {
                    keystr.set(itr.nextToken());
                   context.write(keystr, i);
                  }*/
        }
    }




    //2自己的reduce类
    //  reduce类的输入,其实就是map类中map方法的输出                            输入key  输入value  输出key  输出value
    public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable>{
            IntWritable countwritable = new IntWritable();
        @Override
        //Map类的map方法的数据输入到Reduce类的group方法中,得到<text,it(1,1)>,再将这个数据输入reduce类到reduce方法中
        protected void reduce(Text inputkey, Iterable<IntWritable> inputvalue,
                Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
            //得到了key
            String key = inputkey.toString();
            //迭代Iterable,把每一个值相加
            int count = 0;
            //循环遍历迭代器中的所有值,做相加
            for (IntWritable intWritable : inputvalue) {
                count = count + intWritable.get();
            }
            //把值设置到IntWritable,等待输出
            countwritable.set(count);
            System.out.println("reduce输出结果:key : "+key+" , "+ count);
            context.write(inputkey, countwritable);
        }


    }
    //3运行类,run方法,在测试的时候使用main函数,调用这个类的run方法来运行

    /**
     * 
     * @param args 参数是要接受main方法得到的参数,在run中使用
     * @return
     * @throws Exception
     */
    public int run(String[] args) throws Exception {  
        //hadoop的配置的上下文!
        Configuration configuration = new Configuration();  
        //通过上下文,构建一个job实例,并且传入任务名称,单例!
        Job job = Job.getInstance(configuration, this.getClass().getSimpleName());

        //这参数必须添加,否则本地运行没有问题,服务器上运行会报错
        job.setJarByClass(MyMapReduce.class);

        //设置任务从哪里读取数据?
        //调用这个方法的时候,要往args中传入参数,第一个位置上要传入从哪里读数据
        Path inputpath = new Path(args[0]);
        FileInputFormat.addInputPath(job, inputpath);
        //设置任务结果数据保存到哪里?
      //调用这个方法的时候,要往args中传入参数,第二个位置上要传入结果数据保存到哪里
        Path outputpath = new Path(args[1]);
        FileOutputFormat.setOutputPath(job, outputpath);

        //设置mapper类的参数
        job.setMapperClass(MyMapper.class);
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
        job.setNumReduceTasks(2);

        //设置reduce类的参数
        job.setReducerClass(MyReducer.class);
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        // submit job -> YARN  
        boolean isSuccess = job.waitForCompletion(true);  
        return isSuccess ? 0 : 1;  
    }  


    public static void main(String[] args) {
        args= new String[]{
                "hdfs://192.168.6.129:8020/1.txt",
                "hdfs://192.168.6.129:8020/output"
        };

        MyMapReduce mr = new MyMapReduce();
        try {
            int success = -1; 
            success = mr.run(args);
            System.out.println("success:"+success);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

接下来就是坑了。

3号坑:

Exception in thread "main" java.lang.NullPointerException atjava.lang.ProcessBuilder.start(Unknown Source)

An internal error occurred during: "Map/Reducelocation status updater".java.lang.NullPointerException

解决方式:

如果出现这样的问题,就是上文的配置你没配置好,好好检查下!然后在hdfs上创建目录,上传文件试试,如果配置好了,应该不会有这样的问题。

4号坑:

Failed to locate the winutils binary in the hadoop binary path java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.

解决方式:

这里其实是因为在Windows下面运行mr代码必须有个文件叫做winutil.exe,默认解压的hadoop的bin目录下是没有的,自己下载一个然后放到hadoop目录的bin当中,程序会根据HADOOP_HOME找到bin目录下面的winutil.exe,但是有时候其实你都配置好了,它还报这个错,这时候就要修改源码了(看看源码是哪里获取的,你去手动写一个你正确的路径)。来看看图:

就是这个属性,修改下!!那怎么改,有个很简单的方法,Ctrl+A(全选),然后Ctrl+C(复制),把整个类复制下来,然后看下图!

点击画红圈的地方,Ctrl+V粘贴进去,他会自动生成想源码那样的包,然后直接改这个生成的java类,把350行改成:

完成!

5号坑:

Exception in thread "main"java.lang.UnsatisfiedLinkError:org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)

解决方式:

修改下源码就可以搞定了,其实没有必要把源码包里的.class文件反编译出来,修改,再重新打成jar包,你只要直接点开NativeIO这个类,然后Ctrl+A全文复制,再左键单击你的项目的文件夹(如下如点选src/main/java),最后Ctrl+V这样就会直接生成对应的包名和类。

接着修改下570行的return,注释掉原来的return,直接让代码return true就可以了。如下图:

在本地测试代码。成功运行就会出现一下的结果(这里比较长,就截一部分图):

红色不是错误,而是日志文件,可以添加也可以不添加,没有也没关系。如果要添加

那么本地测试就完全完成了。接下来就是打包jar包。

打包jar包

这个操作如果是经常写项目就很简单了。没有什么坑,直接export就行。

然后跟着next就行了。

在服务器上测试

最后一步,直接把jar包通过FileZila传到服务器。

最后就是测试程序,敲代码。

[songjian@learn hadoop-2.7.3]$ bin/yarn jar may.jar /1.txt /output

然后耐心等一等,就可以跑完啦!!

打个总结

那么综上所述啦,收获不少,这两天挺烦的,遇到各种头疼的bugs,不过还好都解决了。剩下的话其实程序并没有写的很完整,到时候还会在大数据的推文中继续学习。

代码请前往GitHub或者直接在这里复制。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 卡尼慕 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
大数据
全栈大数据产品,面向海量数据场景,帮助您 “智理无数,心中有数”!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档