前言:
Hadoop是一个分布式系统,它由两大核心设计组成:
- HDFS:分存系文件系统
- MapReduce:大数据计算编程模型,
通过Hadoop可以在不了解分布式底层细节的情况下,开发分布式程序,充分利用集群的威力进行高速运算和存储。
通常而言,学习一门新的编程技术,搭建开发环境总是最难的,总会碰到各种各样的问题,一点点消磨耐心,这时如果没有抵住压力,就容易让人半途而废。我在搭建环境时同样碰到了各种各样的问题,在此做个记录,同时希望能为后来者提供些帮助,为简单起见本次搭建的Hadoop为伪分布式,即一台主机,操作系统为Ubuntu 16.04 LTS ,安装的Hadoop版本为3.1.2.
Hadoop环境搭建主要分成以下几个部分:
- JDK配置
- SSH配置
- Hadoop配置
- Eclipse+maven 工程设置
- JDK配置
Hadoop运行环境依赖JDK,因此在运行之前需要安装JDK,目前JDK最新的版本为12.0.2,Hadoop3.1.2版本与该版本的兼容性存在问题,初步测试安装JDK 12.0.2版本时,在访问Hadoop的web管理页面时的目录浏览功页面时会出现错误:Failed to retrieve data from /webhdfs/v1/?op=LISTSTATUS: Server Error,如下图所示:
但通过Hadoop的命令行或API接口上传,下载文件没有发现问题,保守起见,建议安装JDK的8u221版本,以免出现不可预料的问题。
JDK-8U221的下载地址为:
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
这里我选择 jdk-8u221-linux-x64.tar.gz ,下载后可右击文件,在弹出的菜单中点击解压:
打开终端:输入 sudo gedit /etc/profile
在文件最尾处输入:
export JAVA_HOME=/home/cuiweican/Downloads/jdk1.8.0_221
export CLASSPATH=".:$JAVA_HOME/lib:$CLASSPATH"
export PATH="$JAVA_HOME/:$PATH"
export PATH="$JAVA_HOME/bin:$PATH"
保存文件
重启计算机 完成JDK的环境配置
- SSH免密登陆配置
Hadoop需要SSH提供远程连接集群中各计算机的能力,因此需安装SSH,
这里演示如何在两台计算机之间配置免密登陆
- 服务器IP:192.168.110.128 (被远程控制端)
- 客户端IP: 192.168.110.129
1:在服务器及客户端中各执行命令: sudo apt-get install ssh安装ssh
2: 在客户端 执行 ssh-keygen 回车 ,生成key的过程中需要输入文件名及密码,一般情况下直接回车即可。默认情况下会在存放在 /home/XXXX/.ssh/ 生成两个文件id_rsa及id_rsa_pub
2:上传公钥文件至服务器
在客户端执行 $ ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.110.128
3:在服务器端执行
chmod 755 ~
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
4:在客户端执行:ssh-add
至此,完成ssh的免密配置
因为我们这里搭建的是伪分布式hadoop, 只有一台主机,只需要把公钥上传至本机即可,在第二步可执行命令:cat~/.ssh/id_dsa.pub>> ~/.ssh/authorized_keys
- Hadoop配置
Hadoop下载地址为:https://hadoop.apache.org/releases.html
这里下载3.12版本。
配置参数
1:打开hadoop/etc/haddop/core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://192.168.110.128:9000</value>
</property>
<!-- 配置网页访问账户,默认账户为do.who,权限很低,不能在浏览器端上传文件,操作文件侠等操作-->
<property>
<name>hadoop.http.staticuser.user</name>
<value>cuiweican</value>
</property>
</configuration>
说明:
fs.defaultFS: 分布式文件系统的访问地址
2:打开hadoop/etc/haddop/hdfs-site.xml
<configuration>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/home/cuiweican/hadoop/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/home/cuiweican/hadoop/dfs/data</value>
</property>
<property>
<name>dfs.repliction</name>
<value>3</value>
</property>
</configuration>
2:打开hadoop/etc/haddop/mapred-site.xml
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>hdfs://192.168.110.128:9001</value>
</property>
</configuration>
3:打开hadoop/etc/haddop/hadoop-env.sh
在文件尾添加以下行:
export JAVA_HOME=/home/cuiweican/Downloads/jdk-12.0.2
4:启动hadoop
执行 /hadoop-3.1.2/sbin/start-all.sh
启动完毕后可在浏览器中输入查看管理页面
- 示例项目 文本字数:
Pom.xml
<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>com.zm</groupId>
<artifactId>hadoop</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hadoop</name>
<url>http://maven.apache.org</url>
<properties>
<hadoop.version>3.2.0</hadoop.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</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-hdfs</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>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.zm.hadoop.App</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Java
package com.zm.hadoop;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.map.TokenCounterMapper;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.reduce.IntSumReducer;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
try {
Configuration conf = new Configuration();
// 这个解决hdfs问题
conf.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());
// 这个解决本地file问题
conf.set("fs.file.impl", org.apache.hadoop.fs.LocalFileSystem.class.getName());
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(App.class);
job.setMapperClass(TokenCounterMapper.class);
job.setCombinerClass(IntSumReducer.class);
job.setReducerClass(IntSumReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
String filePath = "hdfs://192.168.110.128:9000/test/README.txt";
String filePath1 = "hdfs://192.168.110.128:9000/test/README1.txt";
FileInputFormat.addInputPath(job, new Path( (filePath) ));
FileOutputFormat.setOutputPath(job, new Path( (filePath1) ));
System.exit(job.waitForCompletion(true) ? 0 : 1);
} catch (Exception e) {
e.printStackTrace();
}
}
}