likes
comments
collection
share

三十分钟简易部署 Hadoop 和上手使用

作者站长头像
站长
· 阅读数 4

👈👈👈 欢迎点赞收藏关注哟

一. 前言

一直想学大数据的一些框架 ,对于初学者者来说, 可以从 Hadoop 入手。

Hadoop 虽然网络上认为其在应用上已经被 HBase , Hive 所超越 ,但是这些框架底层还是基于 Hadoop 的,所以学习它很有必要。

更何况现在的新框架很多思想都是基于 Hadoop ,我们可以不用,但是不能不懂它。

❗❗❗注意注意注意 : Docker 包有点,如果要做后面的自定义 MapReduce 需要 JDK 1.7 的编译环境。

整个过程我摸索花了一下午 ,但是照着这个文档玩应该能30分钟体验,给个赞吧👍👍!!

二. Docker 部署 Hadoop

初期学习过程中,就不考虑集群的一系列部署方式了,这里仅通过 Docker 快速部署一个单机应用

简单启动 :

三十分钟简易部署 Hadoop 和上手使用

三十分钟简易部署 Hadoop 和上手使用

应用案例 :

Hadoop 本身提供了很多的 Demo ,我们可以下载对应源码直接看这些 Demo 并且可以直接运行这些 Demo :

- 一般情况下安装路径在 /usr/local , 这里版本是 hadoop-2.7.0

// S1 : 进入安装目录 (上面执行完应该是直接进入,也可以手动进入)
- 手动 : docker exec -it ${CONTAINER ID} /bin/bash
cd /usr/local/hadoop-2.7.0


// S2 : 执行案例 Demo (这里可以看到有对应的 Example 可以使用)
bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.0.jar grep input output 'dfs[a-z.]+'

执行后会得到以下的结果 :

bash-4.1# bin/hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.0.jar grep input output 'dfs[a-z.]+'
24/02/25 01:45:55 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
24/02/25 01:45:57 INFO input.FileInputFormat: Total input paths to process : 31
24/02/25 01:45:57 INFO mapreduce.JobSubmitter: number of splits:31
24/02/25 01:45:57 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1708842492485_0001
24/02/25 01:45:58 INFO impl.YarnClientImpl: Submitted application application_1708842492485_0001
24/02/25 01:45:58 INFO mapreduce.Job: The url to track the job: http://b0376519f71c:8088/proxy/application_1708842492485_0001/
24/02/25 01:45:58 INFO mapreduce.Job: Running job: job_1708842492485_0001
24/02/25 01:46:06 INFO mapreduce.Job: Job job_1708842492485_0001 running in uber mode : false
24/02/25 01:46:06 INFO mapreduce.Job:  map 0% reduce 0%
.......
24/02/25 01:47:25 INFO mapreduce.Job:  map 100% reduce 100%
24/02/25 01:47:25 INFO mapreduce.Job: Job job_1708842492485_0001 completed successfully
24/02/25 01:47:25 INFO mapreduce.Job: Counters: 49
        // 。。。。 一些性能和统计数据 
	Shuffle Errors
		BAD_ID=0
		CONNECTION=0
		IO_ERROR=0
		WRONG_LENGTH=0
		WRONG_MAP=0
		WRONG_REDUCE=0
	File Input Format Counters 
		Bytes Read=76717
	File Output Format Counters 
		Bytes Written=437
24/02/25 01:47:25 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
24/02/25 01:47:25 INFO input.FileInputFormat: Total input paths to process : 1
24/02/25 01:47:25 INFO mapreduce.JobSubmitter: number of splits:1
24/02/25 01:47:25 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1708842492485_0002
24/02/25 01:47:25 INFO impl.YarnClientImpl: Submitted application application_1708842492485_0002
24/02/25 01:47:25 INFO mapreduce.Job: The url to track the job: http://b0376519f71c:8088/proxy/application_1708842492485_0002/
24/02/25 01:47:25 INFO mapreduce.Job: Running job: job_1708842492485_0002
24/02/25 01:47:37 INFO mapreduce.Job: Job job_1708842492485_0002 running in uber mode : false
24/02/25 01:47:37 INFO mapreduce.Job:  map 0% reduce 0%
24/02/25 01:47:42 INFO mapreduce.Job:  map 100% reduce 0%
24/02/25 01:47:49 INFO mapreduce.Job:  map 100% reduce 100%
24/02/25 01:47:49 INFO mapreduce.Job: Job job_1708842492485_0002 completed successfully
24/02/25 01:47:49 INFO mapreduce.Job: Counters: 49
// .... 与上文类似

三. 图形界面

3.1 关于 Hadoop 的各个端口

  • HDFS 部分 :
    • 50070NameNode 的 Web 端口号
    • 50075DateNode 的 Web 端口号
    • 8020 : HDFS 客户端端口号 (用于对文件系统进行访问)
  • YARN 部分 :
    • 8088 : ResourceManager Web 管理页

NameNode 用来存 HDFS 元数据 ,DataNode 用来存实际数据 ,ResourceManager 用来做协调和管理。具体的下一篇讲。

PS :这里还有一些其他的端口就不说明了,具体的可以看官方文档

2.2 NameNode Web 页面

  • Overive : 包含了 NameNode 的基础信息(启动时间,运行情况,节点信息,节点使用情况,状态等等)
  • Datenodes : DateNode 的具体详情 ,包括节点和节点的使用总额

2.3 ResourceManager Web

首先还是要了解下 ResourceManager ,在 Hadoop1.x 里面 ,通常是 JobTracker ,在 2.X 里面则由 ResourceManager 来集中调配资源。

进入其Web 页面(8088),就可以看到上文中我们执行的任务详情.

三十分钟简易部署 Hadoop 和上手使用

四. Hadoop MapReduce 计算

上面已经了解了一个 MapReduce 的运行,下面就来看看如何定义一个可执行的jar :

4.1 首先看写法

public class WordCount {
    
     // 处理输入数据,输出中间键值对
    public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
             // ......
        }
    }

    // 处理中间键值对,输出最终结果  
    public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
        @Override
        protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            // 示例:统计单词出现次数.....
        }
    }

    // 创建一个 Job ,用于 Hadoop 进行调用
    public static void main(String[] args) throws Exception {
        String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
        Job job = Job.getInstance(conf, "word count");
        // 核心一 : 输入路径 , 从 Run 命令中获取  
        FileInputFormat.addInputPath(job, new Path(0));
        // 核心二 : 输出路径 , 从 Run 命令中获取  
        FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
        System.exit(job.waitForCompletion(true) ? 0 : 1);
    }
}

之前说了, MapReduce 阶段分为 Mapper 和 Reduce 两个阶段,我们只需要创建两个 class ,分别实现 Mapper 阶段的 文本解析Reduce 阶段的 结果统计 即可。

而后生成一个 Job ,用于在 Hadoop 中进行执行。

4.2 一个完整的自定义项目

S1 : 添加 Maven 依赖 , 使用对应的版本即可

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

S2 : 创建好 Mapper 类 和 Reduce 类

public static class MyMapper extends Mapper<LongWritable, Text, Text, IntWritable> {
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        // 处理输入数据,输出中间键值对
        // 示例:统计单词出现次数
        String[] words = value.toString().split("\s+");
        for (String word : words) {
            context.write(new Text(word), new IntWritable(1));
        }
    }
}

public static class MyReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        // 处理中间键值对,输出最终结果
        // 示例:统计单词出现次数
        int sum = 0;
        for (IntWritable value : values) {
            sum += value.get();
        }
        context.write(key, new IntWritable(sum));
    }
}

S3 : 创建好 Job 类

public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "MyMapReduceJob");

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

    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    
    // Job 的类名,不要不行,会找不到 Class
    job.setJarByClass(MyMapReduceJob.class);

    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    // 基于执行的运行命令
    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
}

S4 : 打包后上传 Hadoop 服务器

因为我这里使用的是 Docker ,也没整Volume 镜像卷,就稍微需要 Copy 一下

docker cp /home/hadoop-word-count-1.0.jar <CONTAINER ID>:/home/hadoop-word-count-1.0.jar

cd /usr/local/hadoop-2.7.0

// 方式一 : 全量执行
bin/hadoop jar /home/hadoop-word-count-1.0.jar grep input output 'dfs[a-z.]+'
// 方式二 : 执行执行的文件 
bin/hadoop jar /home/hadoop-word-count-1.0.jar org.example.MyMapReduceJob input output 'dfs[a-z.]+'

来详细看一下上面的执行语句 :

  • hadoop-word-count.jar : 我上传的 jar 包文件路径
  • com.example.MyMapReduceJob : 可以指定要执行的 Job
  • input : 深入的数据路径(数据需要先传入 HDFS ,具体见下文
  • output : 输出的数据路径 (需要有路径,可以没文件,文件名重复会有异常

S5 : 准备你的数据源文件

// 1. 查看当前 HDFS 的文件及路径 (hadoop-2.7.0 目录下)
bin/hadoop fs -ls /
bin/hadoop fs -ls -R /


// 2. 创建一个根路径
bin/hadoop fs -mkdir /self


// ---- 这里就能看到有两个文件夹了
bash-4.1# bin/hadoop fs -ls /
Found 2 items
drwxr-xr-x   - root supergroup          0 2024-02-25 04:55 /self
drwxr-xr-x   - root supergroup          0 2015-07-22 11:17 /user

// 3. 准备一个 input.ext
Hello World
Hello Hadoop
MapReduce Example
Hadoop is powerful

// 4. 上传的 HDFS (首先在外部把文件传入 Docker ,再到 Docker 里面传入 HDFS)
docker cp /home/input.txt <CONTAINER ID>:/home/input.txt
bin/hadoop fs -put /home/input.txt /self/input.txt

// 5. 查看文件是否成功
bin/hadoop fs -cat /self/input.txt

最终执行结果

// 运行 Jar 和 录入的文件路径
bin/hadoop jar /home/hadoop-word-count-.jar org.example.MyMapReduceJob /self/input.txt /self/out.txt 'dfs[a-z.]+'


// 执行情况 : 
bash-4.1# bin/hadoop jar /home/hadoop-word-count-7.jar org.example.MyMapReduceJob /self/input.txt /self/out7.txt 'dfs[a-z.]+'
24/02/25 07:45:56 INFO client.RMProxy: Connecting to ResourceManager at /0.0.0.0:8032
24/02/25 07:45:56 WARN mapreduce.JobResourceUploader: Hadoop command-line option parsing not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this.
24/02/25 07:45:56 INFO input.FileInputFormat: Total input paths to process : 1
24/02/25 07:45:57 INFO mapreduce.JobSubmitter: number of splits:1
24/02/25 07:45:57 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1708862965396_0010
24/02/25 07:45:57 INFO impl.YarnClientImpl: Submitted application application_1708862965396_0010
24/02/25 07:45:57 INFO mapreduce.Job: The url to track the job: http://809349f6ff4a:8088/proxy/application_1708862965396_0010/
24/02/25 07:45:57 INFO mapreduce.Job: Running job: job_1708862965396_0010
24/02/25 07:46:04 INFO mapreduce.Job: Job job_1708862965396_0010 running in uber mode : false
24/02/25 07:46:04 INFO mapreduce.Job:  map 0% reduce 0%
24/02/25 07:46:09 INFO mapreduce.Job:  map 100% reduce 0%
24/02/25 07:46:15 INFO mapreduce.Job:  map 100% reduce 100%
24/02/25 07:46:15 INFO mapreduce.Job: Job job_1708862965396_0010 completed successfully
24/02/25 07:46:15 INFO mapreduce.Job: Counters: 49


// PS : 因为跑了多个,所以会有很多 ,先查出列表
bash-4.1# bin/hadoop fs -ls -R /
drwxr-xr-x   - root supergroup          0 2024-02-25 07:46 /self
-rw-r--r--   1 root supergroup         64 2024-02-25 07:14 /self/input.txt
drwxr-xr-x   - root supergroup          0 2024-02-25 07:33 /self/out.txt
drwxr-xr-x   - root supergroup          0 2024-02-25 07:37 /self/out1.txt
drwxr-xr-x   - root supergroup          0 2024-02-25 07:42 /self/out6.txt
drwxr-xr-x   - root supergroup          0 2024-02-25 07:46 /self/out7.txt
-rw-r--r--   1 root supergroup          0 2024-02-25 07:46 /self/out7.txt/_SUCCESS
-rw-r--r--   1 root supergroup         63 2024-02-25 07:46 /self/out7.txt/part-r-00000

// 统计的结果 : 
bin/hadoop fs -cat /self/out7.txt
bash-4.1# bin/hadoop fs -cat /self/out7.txt/part-r-00000
Example	1
Hadoop	2
Hello	2
MapReduce	1
World	1
is	1
powerful	1

补充碰到的问题 :


// 这里碰到个大坑,Docker 里面的环境还在用 1.7 , 会导致包跑不起来 :
// 这里需要把 IDEA 里面项目环境改成 Java-1.7 ,Maven 也得改,折腾完后上传 :
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/example/MyMapReduceJob : Unsupported major.minor version 52.0
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:274)
	at org.apache.hadoop.util.RunJar.run(RunJar.java:214)
	at org.apache.hadoop.util.RunJar.main(RunJar.java:136)


// IDEA Maven 1.7 下载 文件 protocols 异常
//- Maven Runner 里面 VM Options 添加
-Dhttps.protocols=TLSv1.2


// Maven 对应 1.7 的下载 : 
https://maven.apache.org/docs/history.html

// JDK 1.7 下载 : 
https://www.oracle.com/java/technologies/javase/javase7-archive-downloads.html

补充一 : 图形界面及RestAPI进行访问

一般这里可以通过 API 访问 ,也可以通过图形界面访问 ,我这里用的 hue 图形界面

docker run -it -p 8888:8888 gethue/hue:latest


- 也可以使用 Rest API 
http://121.41.122.204:50070/webhdfs/v1/user/root/input?op=LISTSTATUS
{
    "FileStatuses": {
        "FileStatus": [
            {
                "accessTime": 1437578277549,
                "blockSize": 134217728,
                "childrenNum": 0,
                "fileId": 16389,
                "group": "supergroup",
                "length": 4436,
                "modificationTime": 1437578278450,
                "owner": "root",
                "pathSuffix": "capacity-scheduler.xml",
                "permission": "644",
                "replication": 1,
                "storagePolicy": 0,
                "type": "FILE"
            }
        ]
    }
}

执行完成也可以看到执行的 Job

三十分钟简易部署 Hadoop 和上手使用

总结

很不幸的是 ,找的这个最多的 Docker 镜像只支持 JDK 1.7 编译 . 如果只是为了体验应该问题不大,深度使用就会有很大问题。

所以后续还会尝试其他的部署方式,搞了这么久,全部回退也太可惜了,所以还是发出来。

虽然受环境限制不太理想,但是写法和 HDFS 的用法是一致的。

当然这一篇没体验到 Hadoop 的快速和优势,后续会尝试下。

参考文档 :

blog.csdn.net/Andy_Health…

转载自:https://juejin.cn/post/7339155841181007898
评论
请登录