写在前面

最近在做大数据项目,首先就是配置Hadoop集群,之后就是通过IDEA来连接虚拟机中搭建好的HDFS,但是由于是mac系统,而且网络上面IDEA的配置教程相比于eclipse来说大多都不详细清楚,所以遇到了很多的坑,解决问题之后把相关的过程和方法写下来供交流参考。

配置虚拟机Hadoop集群

这个网上有很多的教程,我就不写了

在mac上面配置Hadoop 环境

这里建议把之前在linux上面配置好的Hadoop文件夹直接从虚拟机上面传出来,这样既省事又可以避免出错,毕竟配置环境还是比较复杂的。从虚拟机上面导出来之后,可以开始配置mac的Hadoop环境变量了。
终端输入命令:

sudo vim .bash_profile

在其中的空闲位置处写下环境变量,这里HADOOP_HOME是你从虚拟机中导出来的Hadoop文件路径,我的在/Volumes/Al的扩展/Hadoop/hadoop-2.7.7,我配置了HADOOP_USER_NAME=root是为了等会要跑程序的用户是root用户。

#hadoop
export HADOOP_HOME=/Volumes/Al的扩展/Hadoop/hadoop-2.7.7
export HADOOP_USER_NAME=root
export PATH=$PATH:$HADOOP_HOME/sbin:$HADOOP_HOME/bin

之后保存文件,然后

source .bash_profile

这时在mac终端上输入hadoop就可以看到这样的信息
在这里插入图片描述
这样就算成功啦!

在IDEA中使用Hadoop的插件

插件的代码地址:https://github.com/fangyuzhong2016/HadoopIntellijPlugin
如果下载不到的老哥也可以从下面这个链接下载
链接:https://pan.baidu.com/s/1qRBia2dJvCeZbon8q5edHQ 密码:td8r
下载之后要进行编译,需要电脑有maven3环境和1.8的jdk,只能是1.8!上面有讲下载下来需要在里面改hadoop版本为本机hadoop版本,但是我没改也可以使用,
把这个zip下载下来之后,打开IDEA,创建maven项目,然后使用“command + ,“来打开Preferences,找到里面的Plugin插件设置
在这里插入图片描述
点击上方的齿轮,选择从硬盘安装
在这里插入图片描述
找到你下载的安装包的位置
在这里插入图片描述
点击open,会显示这个
在这里插入图片描述
这时候OK就可以了,这时候重启一下IDEA,就会发现右上角多了个Hadoop的选项。这里选择设置
在这里插入图片描述
连接名称随便写,描述随便写,下面两个地址要填虚拟机中的那台master机的ip地址,第一个端口是虚拟机配置Hadoop的时候可以得到的,第二个端口写9000。不要点击下面的测试,是不可能成功的,直接点击确定。
在这里插入图片描述
然后你会发现在IDEA的最左侧多了一个黄色的小象,点开它,如果可以成功连接上的话,可以看到你hdfs中的文件
在这里插入图片描述
但是他不如eclipse上面对应的插件好用,刷新没有那么快,可能有些时候需要手动一下。至此我们成功连接上虚拟机中的HDFS

配置MAVEN项目来运行我们第一个MapReduce程序

一开始不知道maven项目可以直接自动导入依赖,按照网上的教程一个一个从我的hadoop文件里面吧jar包导入进去,给我累坏了,后来改了项目中的pom.xml文件才知道,直接从阿里云的maven仓库自动导入依赖。修改项目中的pom.xml文件,把groupId和artifactId改成自己的,添加阿里云的仓库,并且加入slf4的日志输出:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.Al</groupId>
    <artifactId>HadoopTest2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <repositories>
        <repository>
            <id>aliyun</id>
            <url>https://maven.aliyun.com/repository/public</url>
        </repository>
    </repositories>
    <properties>
        <hadoop.version>2.7.7</hadoop.version>
    </properties>


    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-core -->
        <!--        <dependency>-->
        <!--            <groupId>org.apache.hadoop</groupId>-->
        <!--            <artifactId>hadoop-core</artifactId>-->
        <!--            <version>1.2.1</version>-->
        <!--        </dependency>-->

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.7.7</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.26</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.6.4</version>
        </dependency>
    </dependencies>
</project>

刚把这些内容复制进去的时候会发现他们是红色的字体,因为jar包没有导入进来,这时候看IDEA的右下角你会发现他在飞快的导包,过一会完成了我们的字体也就恢复常规颜色了。这时我们使用hadoop的包就不会报错了。之后要在resource文件夹中配置log4j

log4j.rootLogger=INFO, stdout, R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=example.log

log4j.appender.R.MaxFileSize=100KB
# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n

在这里插入图片描述
现在开始写我们第一个WordCount小程序吧!新建一个JAVA类,然后把下面的代码粘贴上去。(代码不是本人的,部分注释是)

package com.Al;

import java.io.IOException;
import java.util.Arrays;

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.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.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

/**
 * 统计文本中单词出现的次数 以文件形式输出
 *
 * @author lyd
 */
public class MyWordCount {

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {

        //1.设置conf对象,并配置hdfs路径
        //2.设置job对象,在job对象中设置 Jar map reduce reduce的输出类型(key value) 输出格式化方式
        //文件的输入和输出路径  系统退出
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://master:9000"); //设置成集群的key,我的是fs.defaultFS,value是上一步配的hdfs的地址

        Job job = Job.getInstance(conf, "wordcount");
        job.setJarByClass(MyWordCount.class);

        job.setMapperClass(MyMapper.class);
        job.setReducerClass(MyReducer.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(IntWritable.class);

        job.setInputFormatClass(TextInputFormat.class);

        FileInputFormat.addInputPath(job, new Path("/222.txt")); //设置成你要转换的文本,我这里是222.txt,要在hdfs中存在
        Path outputPath = new Path("/wordcount/");
        FileSystem.get(conf).delete(outputPath, true);// 检查是否存在输出路径,如果存在就先删除
        FileOutputFormat.setOutputPath(job, outputPath);
        System.exit(job.waitForCompletion(true) ? 0 : 1);


    }

    /**
     * @param KEYIN    →k1 表示每一行的起始位置(偏移量offset)
     * @param VALUEIN  →v1 表示每一行的文本内容
     * @param KEYOUT   →k2 表示每一行中的每个单词
     * @param VALUEOUT →v2 表示每一行中的每个单词的出现次数,固定值为1
     * @author lyd
     * @version 1.0
     */
    //Mapper中第三个和第四个参数必须和Reducer中第一个和第二个参数相同,输出结果<key, {value}>
    public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {

        @Override
        protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
                throws IOException, InterruptedException {

            System.err.println("key的值为:" + key.toString());
            System.err.println("value的值为:" + value.toString());
            String[] words = value.toString().split("\\s+");
            System.out.println(Arrays.toString(words) + "-_-");
            IntWritable one = new IntWritable(1);
            Text text = new Text();
            for (String word : words) {
                System.out.println("------------->" + word);
                text.set(word);
                context.write(text, one); //连接map和reduce的context
            }

        }

    }

    /**
     * @param KEYIN    →k2 表示每一行中的每个单词
     * @param VALUEIN  →v2 表示每一行中的每个单词的出现次数,固定值为1
     * @param KEYOUT   →k3 表示每一行中的每个单词
     * @param VALUEOUT →v3 表示每一行中的每个单词的出现次数之和
     * @author lyd
     * @version 1.0
     */
    public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

        @Override
        protected void reduce(Text value, Iterable<IntWritable> iterable,
                              Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {

            int sum = 0;
            IntWritable i = new IntWritable();
            System.err.println("value的值为:" + value + " end!");
            for (IntWritable intWritable : iterable) {
                System.err.println("===>" + intWritable + "<====");
                sum += intWritable.get();
            }
            i.set(sum);
            context.write(value, i);
        }

    }

}

这时候点击main方法旁边的绿色箭头来运行程序,可以看到程序成功执行,在这里插入图片描述
稍等一会我们会在hdfs里面发现多了一个wordcount文件夹
在这里插入图片描述
SUCCESS是成功执行的标志,下面那个文件就是我们最后的结果,我们可以在项目的data文件夹中同步找到这个文件,看一下程序输出的结果吧。
在这里插入图片描述
到此为止就全部结束啦!希望能对你有帮助哦~

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐