说明
本文介绍hadoop伪分布的搭建和配置, 并用于本地测试.
准备
拥有一台装有linux的计算机
这台计算机装有oracle jdk, 并且配置好了jdk
这台电脑安装了ssh, 并且配置好了ssh.
在apache基金会网站上下载hadoop压缩包, 并存放在这台计算机上.
安装与配置
解压hadoop压缩包, 因为hadoop压缩包使用的tar+gzip, 所以可以直接使用下面命令进行解压:
tar -xf hadoop.tar.gz
接着是把hadoop安装到相应的目录中, 有多个被选的目录可以选择:
/opt/
/usr/share/
/usr/local/share/
/user/java/
虽然, 对于hadoop来说, 只要不放在有中文或者空格的目录下都行, 但是为了方便操作, 还是放在比较常用的位置上.
本文将其放在/opt/目录下. 使用下面命令进行实现:
mv /path/to/hadoop /opt/hadoop
然后需要修改环境变量, 修改/etc/profile文件, 添加如下代码:
HADOOP_HOME=/opt/hadoop/
PATH=$PATH:$HADOOP_HOME/bin/
export HADOOP_HOME PATH
将hadoop安装目录添加到环境变量中, 并将hadoop的bin目录添加到PATH变量中.
接着是配置hadoop, 由于需要搭建的是伪分布的hadoop, 因此, 只需要修改core-site.xml和hdfs-site.xml文件
首先是core-site.xml文件.
首先修改fs.defaultFS属性, 用于设置控制节点的端口号和地址. 本地伪分布的话, 肯定是设置成localhost
在文件的根节点下添加如下代码:
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
hadoop需要一个临时目录用于存放计算中间文件和存储文件, 默认情况下, hadoop会在/tmp/目录下创建
但是这个目录下的文件, 在重启之后会被删除.
所有, 有必要重新设置一个目录用于存放”临时文件”. 设置hadoop.tmp.dir属性, 标识”临时目录”的位置.
在gen标签下添加下面代码:
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop</value>
</property>
接着是hdfs.xml文件, 用于配置hdfs. 默认情况下, 同一个块会被分配到三个不同的节点上. 然后, 这次配置的是
伪分布, 只需要一份即可, 需要设置dfs.replication, 在根标签下添加下面代码:
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
测试
配置完毕, 接着是测试配置结果.
首先, 需要格式化文件系统, 使用下面代码进行实现:
bin/hdfs namenode -format
然后是启动hdfs了, 使用下面命令进行实现:
sbin/start-dfs.sh
有时候, 启动hdfs会显示无法连接localhost. 首先先确认一下, 计算机的hostname是否为”localhost”.
如果不是, 需要修改hostname, 文件位置为/etc/hostname
接着是创建用户目录, 向hdfs添加数据, 命令如下:
hadoop fs -mkdir /user
hadoop fs -mkdir /user/phantom9999
hadoop fs -mkdir /user/phantom9999/logs
hadoop fs -mkdir /user/phantom9999/logs/input/
hadoop fs -mkdir /user/phantom9999/logs/output/
hadoop fs -put ./nginx.log.bz2 logs/input/
接着是编码.
使用intelli idea编码时, 先设置依赖. 在项目结构中找到模块-依赖, 点击加号, 进行添加. 需要添加的目录分别是:
common, hdfs, mapreduce, yarn, common/lib
设置完依赖, 接着设置生成(artifacts), 创建jar包, 并设置在构建的时候进行打包.
打包完使用一下命令运行jar包:
hadoop jar /path/to/name.jar
贴一下nginx日志分析一个ip数量统计的代码:
package com.logs;
import java.net.URL;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Objects;
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.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;
public class Main {
public static class DoMapper
extends Mapper<Object, Text, Text, IntWritable>{
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] fields = line.split("\"");
String[] ipFields = fields[0].split(" ");
String ip = ipFields[0];
context.write(new Text(ip), new IntWritable(1));
}
}
public static class DoReducer
extends Reducer<Text,IntWritable,Text,IntWritable> {
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
int sum = 0;
for (Text item: values) {
sum += item.get();
}
context.write(key, new IntWritable(sum));
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(conf, "log");
job.setJarByClass(Main.class);
job.setMapperClass(DoMapper.class);
job.setReducerClass(DoReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path("/user/phantom9999/log/input/"));
FileOutputFormat.setOutputPath(job, new Path("/user/phantom/log/output/result"));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}