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

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

首先分享之前的所有文章 >>>> 😜😜😜
文章合集 : 🎁 juejin.cn/post/694164...
Github : 👉 github.com/black-ant
CASE 备份 : 👉 gitee.com/antblack/ca...

一. 前言

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

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

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

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

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

二. Docker 部署 Hadoop

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

简单启动 :

java 复制代码
- Docker 安装最新版本就行 , 这里没特殊要求
- 我的安装流程可见这篇 : https://juejin.cn/post/7231539287459872827#heading-4

// S1 : 下载最新版的 Hadoop Docker 镜像
- 切记需要对应 JDK 版本,不然后面会很麻烦 (例如这个就要 JDK 1.7 编译包)
- 版本号对应关系 : https://blog.csdn.net/m290345792/article/details/106323252
- 这个使用最多,但是8年前就停止更新了,只体验使用,所以还是采用他
docker pull sequenceiq/hadoop-docker

// S2 : 运行 Docker 镜像
docker run -i -t -p 50070:50070 -p 9000:9000 -p 8088:8088 -p 8040:8040 -p 8042:8042  -p 49707:49707  -p 50010:50010  -p 50075:50075  -p 50090:50090 sequenceiq/hadoop-docker /etc/bootstrap.sh -bash

// --------------- 到这里基础安装就完成了,可以通过远程访问
- HDFS:             http://localhost:50070
- ResourceManager:  http://localhost:8088

应用案例 :

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

java 复制代码
- 一般情况下安装路径在 /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.]+'

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

java 复制代码
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 MapReduce 计算

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

4.1 首先看写法

java 复制代码
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 依赖 , 使用对应的版本即可

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>2.7.0</version>
    </dependency>
</dependencies>

S2 : 创建好 Mapper 类 和 Reduce 类

java 复制代码
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 类

java 复制代码
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 一下

java 复制代码
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 : 准备你的数据源文件

java 复制代码
// 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

最终执行结果

java 复制代码
// 运行 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

补充碰到的问题 :

java 复制代码
// 这里碰到个大坑,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 图形界面

java 复制代码
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

总结

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

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

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

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

参考文档 :

blog.csdn.net/Andy_Health...

相关推荐
whinc2 小时前
Rust技术周刊 2026年第17周
后端·rust
whinc2 小时前
Rust技术周刊 2026年第18周
后端·rust
xqqxqxxq2 小时前
Java AI智能P图工具技术笔记
java·人工智能·笔记
whinc2 小时前
Rust技术周刊 2026年第16周
后端·rust
谷雨不太卷2 小时前
进程的状态码
java·前端·算法
方向研究2 小时前
盈利因子策略
大数据
jieyucx3 小时前
Go语言深度解剖:Map扩容机制全解析(增量扩容+等量扩容+渐进式迁移)
开发语言·后端·golang·map·扩容策略
顾温3 小时前
default——C#/C++
java·c++·c#
空中海3 小时前
02 ArkTS 语言与工程规范
java·前端·spring
楚国的小隐士3 小时前
在AI时代,如何从0接手一个项目?
java·ai·大模型·编程·ai编程·自闭症·自闭症谱系障碍·神经多样性