基于Apache的电商数据仓库(二)
欢迎
你好!这是我历经1个半月的学习(Apache和CDH),做完的一个项目,本次和你们分享一下Apache版。
感谢您的阅读!
第1章~第4章在基于Apache的电商数据仓库(一)
第5章~第5章在基于Apache的电商数据仓库(二)
第6章~第8章在基于Apache的电商数据仓库(三)
第8章~第9章在基于Apache的电商数据仓库(四)
第10章~第12章在基于Apache的电商数据仓库(五)
第13章~第13章在基于Apache的电商数据仓库(六)
第14章~第14章在基于Apache的电商数据仓库(七)
第5章 数据采集
需准备:
- 白板机3台。配置好静态ip,关防火墙,创建cluster用户并给予root权限,主机映射,ssh免密,日期时间同步等
- jdk-8u144-linux-x64.tar.gz。并安装好,配置profile,.bashrc,将上一章的jar包写成脚本等
5.1 hadoop安装
- 5.1.1 规划
- HDFS主要配置两大node:namenode和DataNode。
- yarn主要配置两大manager:resourcemanager和nodemanager。
- hadoop102配置NN和DN;hadoop103配置DN;hadoop104配置DN和SNN(secondarynamenode)
- hadoop102配置NM;hadoop103配置RN和NM;hadoop104配置NM
- 5.1.2 安装
正常tar安装即可
- 5.1.3 配置xml
- 配置集群
***core-site.xml***
<!-- 指定HDFS中NameNode的地址 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop102:9000</value>
</property>
<!-- 指定Hadoop运行时产生文件的存储目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-2.7.2/data/tmp</value>
</property>
***hdfs-site.xml***
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
<!-- 指定Hadoop辅助名称节点主机配置 -->
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop104:50090</value>
</property>
***yarn-site.xml***
<!-- reducer获取数据的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!-- 指定YARN的ResourceManager的地址 -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop103</value>
</property>
**配置历史日志服务**
***mapred-site.xml***
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop102:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop102:19888</value>
</property>
<!--第三方框架使用yarn计算的日志聚集功能 -->
<property>
<name>yarn.log.server.url</name>
<value>http://hadoop102:19888/jobhistory/logs</value>
</property>
***yarn-site.xml***
<!-- 日志聚集功能使能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- 日志保留时间设置7天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
**mapred-site.xml**
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
- 配置slaves
vim /opt/module/hadoop-2.7.2/etc/hadoop/slaves
hadoop102
hadoop103
hadoop104
- 分发到haodop103和hadoop104
- 配置HADOOP_HOME(bin和sbin)
- 5.1.4 格式化NN
hdfs namenode -format
- 5.1.5 启动
start-dfs.sh
start-yarn.sh
编写启停脚本
查看
http://hadoop102:50070
http://hadoop103:8088
- 5.1.6 LZO压缩配置
hadoop本身并不支持lzo压缩,故需要使用twitter提供的hadoop-lzo开源组件。
-
环境准备
maven
gcc-c++
zlib-devel
autoconf
automake
libtool
通过yum安装即可 -
下载、安装并编译LZO
wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz
tar -zxvf lzo-2.10.tar.gz
cd lzo-2.10
./configure -prefix=/usr/local/hadoop/lzo/
make
make install
- 编译hadoop-lzo源码
下载hadoop-lzo的源码,下载地址:
https://github.com/twitter/hadoop-lzo/archive/master.zip
解压之后,修改pom.xml
<hadoop.current.version>2.7.2</hadoop.current.version>
声明两个临时环境变量
export C_INCLUDE_PATH=/usr/local/hadoop/lzo/include
export LIBRARY_PATH=/usr/local/hadoop/lzo/lib
编译
进入hadoop-lzo-master,执行maven编译命令
mvn package -Dmaven.test.skip=true
进入target,hadoop-lzo-0.4.21-SNAPSHOT.jar 即编译成功的hadoop-lzo组件
- 将编译好后的hadoop-lzo-0.4.20.jar 放入hadoop-2.7.2/share/hadoop/common/
[cluster@hadoop102 common]$ pwd
/opt/module/hadoop-2.7.2/share/hadoop/common
[cluster@hadoop102 common]$ ls
hadoop-lzo-0.4.20.jar
- 同步hadoop-lzo-0.4.20.jar到hadoop103、hadoop104
[cluster@hadoop102 common]$ xsync hadoop-lzo-0.4.20.jar
- core-site.xml配置支持LZO
<configuration>
<property>
<name>io.compression.codecs</name>
<value>
org.apache.hadoop.io.compress.GzipCodec,
org.apache.hadoop.io.compress.DefaultCodec,
org.apache.hadoop.io.compress.BZip2Codec,
org.apache.hadoop.io.compress.SnappyCodec,
com.hadoop.compression.lzo.LzoCodec,
com.hadoop.compression.lzo.LzopCodec
</value>
</property>
<property>
<name>io.compression.codec.lzo.class</name>
<value>com.hadoop.compression.lzo.LzoCodec</value>
</property>
</configuration>
- 同步core-site.xml到hadoop103、hadoop104
- 启动集群
[cluster@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh
[cluster@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh
- 测试
yarn jar share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount -Dmapreduce.output.fileoutputformat.compress=true -Dmapreduce.output.fileoutputformat.compress.codec=com.hadoop.compression.lzo.LzopCodec /input /output
- lzo文件创建索引
hadoop jar ./share/hadoop/common/hadoop-lzo-0.4.20.jar com.hadoop.compression.lzo.DistributedLzoIndexer /output
- 5.1.7 参数调优
- 调优hdfs-site.xml
dfs.namenode.handler.count=
比如此次进群3台,参数设置为 20*log23=20
- 调优yarn-site.xml
(a)表示该节点上YARN可使用的物理内存总量
yarn.nodemanager.resource.memory-mb
(b)单个任务可申请的最多物理内存量
yarn.scheduler.maximum-allocation-mb
5.2 zookeeper安装
- 5.2.1 安装ZK
- 正常安装即可
tar -zxvf ... -C ...
- 修改zoo.cfg文件
dataDir=/opt/module/zookeeper-3.4.10/datas
需要手动创建datas
- 创建一个myid的文件
cd /opt/module/zookeeper-3.4.10/datas
vim myid
103
- 分发ZK
- 修改每台机器的myid
- 配置ZOOKEEPER_HOME(bin)
- 5.2.2 创建zk启停脚本
- 内容如下
#! /bin/bash
case $1 in
"start"){
for i in hadoop102 hadoop103 hadoop104
do
ssh $i "/opt/module/zookeeper-3.4.10/bin/zkServer.sh start"
done
};;
"stop"){
for i in hadoop102 hadoop103 hadoop104
do
ssh $i "/opt/module/zookeeper-3.4.10/bin/zkServer.sh stop"
done
};;
"status"){
for i in hadoop102 hadoop103 hadoop104
do
ssh $i "/opt/module/zookeeper-3.4.10/bin/zkServer.sh status"
done
};;
esac
- 增加脚本权限
[cluster@hadoop102 bin]$ chmod 777 zk.sh
- 启停脚本
zk.sh start
zk.sh stop
5.3 日志采集的flume安装
- 5.3.1 规划
- 2个采集日志中的flume,1个采集kafka的flume
- hadoop102,hadoop103和hadoop104
- 5.3.2 安装
tar -zxvf ... -C ...
- 5.3.3 配置FLUME_HOME
5.4 kafka安装
-
5.4.1 正常安装
-
5.4.2 配置
配置kafka/config/server.properties
扫描二维码关注公众号,回复: 12914506 查看本文章![]()
修改以下几点
broker.id=103
delete.topic.enable=true
log.dirs=/opt/module/kafka/datas
zookeeper.connect=hadoop102:2181,hadoop103:2181,hadoop104:2181
-
5.4.3 配置KAFKA_HOME
-
5.4.4 分发kafka
5.5 第一层采集通道编写
- 5.5.1 选择source 和 channel
- source:TailDirSource 接近实时读取指定的文件!断点续传功能!
- channel:KafkaChannel 基于kafka,提高了可用性!
- 5.5.2 编写自定义拦截器
public class MyInterceptor implements Interceptor{
//创建一个放置复合要求数据的集合
private List<Event> results=new ArrayList<>();
private String startFlag="\"en\":\"start\"";
@Override
public void initialize() {
}
//核心方法
@Override
public Event intercept(Event event) {
byte[] body = event.getBody();
Map<String, String> headers = event.getHeaders();
String bodyStr = new String(body, Charset.forName("utf-8"));
boolean flag=true;
if (bodyStr.contains(startFlag)) {
headers.put("topic", "topic_start");
flag=ETLUtil.validStartLog(bodyStr);
}else {
headers.put("topic", "topic_event");
flag=ETLUtil.validEventLog(bodyStr);
}
if (!flag) {
return null;
}
return event;
}
@Override
public List<Event> intercept(List<Event> events) {
results.clear();
for (Event event : events) {
Event result = intercept(event);
if (result !=null) {
//放入合法的数据集合中
results.add(result);
}
}
return results;
}
@Override
public void close() {
}
public static class Builder implements Interceptor.Builder{
//从flume的配置文件中读取参数
@Override
public void configure(Context context) {
}
//创建一个拦截器对象
@Override
public Interceptor build() {
return new MyInterceptor();
}
}
}
- 5.5.3 编写flume执行conf
放到flume/myagents下
a1.sources = r1
a1.channels = c1 c2
a1.sources.r1.type=TAILDIR
a1.sources.r1.filegroups=f1
a1.sources.r1.batchSize=1000
a1.sources.r1.filegroups.f1=/tmp/logs/^app.+.log$
a1.sources.r1.positionFile=/opt/module/flume/test/log_position.json
#定义拦截器
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = com.atguigu.dw.flume.MyInterceptor$Builder
a1.sources.r1.selector.type = multiplexing
a1.sources.r1.selector.header = topic
a1.sources.r1.selector.mapping.topic_start = c1
a1.sources.r1.selector.mapping.topic_event = c2
#定义chanel
a1.channels.c1.type=org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c1.kafka.bootstrap.servers=hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.channels.c1.kafka.topic=topic_start
a1.channels.c1.parseAsFlumeEvent=false
a1.channels.c2.type=org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c2.kafka.bootstrap.servers=hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.channels.c2.kafka.topic=topic_event
a1.channels.c2.parseAsFlumeEvent=false
#连接组件
a1.sources.r1.channels=c1 c2
- 5.5.4 测试
flume-ng agent -n a1 -f myagents/f1.conf -c conf/ -Dflume.root.logger=DEBUG,console
- 5.5.5 第一层采集通道总结
从本机读取/ tmp/logs中的日志数据,通过flume, 传输到kafka中
1.保证/tmp/logs中有app-xxx. log
2.使用taildirsource,taildirsource会 讲上次读取数据的位置记录在json文件中可以查看json文件是否更新,判断是否新读取了数据
3.flume agent的工作原理 source ---->拦截器(ETL 1为header添加topic=topic_ start Itopic_ event)----> MuliplexingChannelSelector
(根据自己配置的映射信息,讲指定的event分配到channel)
5.6第二层采集通道编写
- 5.6.1 选择source、channel、sink
- source
kafkasource
数据源在kafka,因此需要使用一个可以对接kafka的source
- channel
为了安全起见,选择filechannel
- sink
目的地在hdfs,使用hdfssink
- 5.6.2 编写flume启动所需的conf
#配置文件编写
a1.sources = r1 r2
a1.sinks = k1 k2
a1.channels = c1 c2
#配置source
a1.sources.r1.type=org.apache.flume.source.kafka.KafkaSource
a1.sources.r1.kafka.bootstrap.servers=hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.sources.r1.kafka.topics=topic_start
a1.sources.r1.kafka.consumer.auto.offset.reset=earliest
a1.sources.r1.kafka.consumer.group.id=CG_Start
a1.sources.r2.type=org.apache.flume.source.kafka.KafkaSource
a1.sources.r2.kafka.bootstrap.servers=hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.sources.r2.kafka.topics=topic_event
a1.sources.r2.kafka.consumer.auto.offset.reset=earliest
a1.sources.r2.kafka.consumer.group.id=CG_Event
#配置channel
a1.channels.c1.type=file
a1.channels.c1.checkpointDir=/opt/module/flume/c1/checkpoint
a1.channels.c1.useDualCheckpoints=true
a1.channels.c1.backupCheckpointDir=/opt/module/flume/c1/backupcheckpoint
a1.channels.c1.dataDirs=/opt/module/flume/c1/datas
a1.channels.c2.type=file
a1.channels.c2.checkpointDir=/opt/module/flume/c2/checkpoint
a1.channels.c2.useDualCheckpoints=true
a1.channels.c2.backupCheckpointDir=/opt/module/flume/c2/backupcheckpoint
a1.channels.c2.dataDirs=/opt/module/flume/c2/datas
#sink
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = hdfs://hadoop102:9000/origin_data/gmall/log/topic_start/%Y-%m-%d
a1.sinks.k1.hdfs.filePrefix = logstart-
a1.sinks.k1.hdfs.batchSize = 1000
a1.sinks.k1.hdfs.rollInterval = 30
a1.sinks.k1.hdfs.rollSize = 134217700
a1.sinks.k1.hdfs.rollCount = 0
a1.sinks.k1.hdfs.fileType = CompressedStream
a1.sinks.k1.hdfs.codeC = lzop
a1.sinks.k2.type = hdfs
a1.sinks.k2.hdfs.path = hdfs://hadoop102:9000/origin_data/gmall/log/topic_event/%Y-%m-%d
a1.sinks.k2.hdfs.filePrefix = logevent-
a1.sinks.k2.hdfs.batchSize = 1000
a1.sinks.k2.hdfs.rollInterval = 30
a1.sinks.k2.hdfs.rollSize = 134217700
a1.sinks.k2.hdfs.rollCount = 0
a1.sinks.k2.hdfs.fileType = CompressedStream
a1.sinks.k2.hdfs.codeC = lzop
#连接组件
a1.sources.r1.channels=c1
a1.sources.r2.channels=c2
a1.sinks.k1.channel=c1
a1.sinks.k2.channel=c2
- 5.6.3 测试
flume-ng agent -n a1 -f myagents/f2.conf -c conf/ -Dflume.root.logger=DEBUG,console
- 5.6.4 第二层采集通道总结
kafkaSource------>FileChannel------>HDFSSink
数据
验证kafkaSource------>FileChannel是否有问题 查看消费者组是否有lag。或运行test2.conf,使用loggersink看是否在控制台有数据的输出。验证时,需要注意,每次消费了数据后,当前消费者组都会提交offset!下次只会从之前的offset继续消费,因此,可以尝试重置offset
验证FileChannel------>HDFSSink是否有问题 遇到问题可以尝试讲日志级别设置 WARN,方便调试
5.7报错总结
- 导入pom.xml的maven-assembly-plugin报错
新建个class,打一次包试试
不行就加个依赖,在次打包
- 前面配置的lzo压缩,在运行f2.conf时报错,说不支持lzo压缩
使用lzo压缩要配置到core-site.xml中,不能配置到mapred-site.xml中,应为之前是MR运行可以读到lzo压缩,但是使用flume时,只能读到8个配置文件,读不到mapred-site.xml