👈👈👈 欢迎点赞收藏关注哟
首先分享之前的所有文章 >>>> 😜😜😜
文章合集 : 🎁 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 部分 :
- 50070 :
NameNode
的 Web 端口号 - 50075 :
DateNode
的 Web 端口号 - 8020 : HDFS 客户端端口号 (用于对文件系统进行访问)
- 50070 :
- 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 的快速和优势,后续会尝试下。