01.04第一篇之集群搭建&数据采集模块

第4 章集群搭建&数据采集模块

4.0 虚拟机准备

4.0.1 虚拟机内存分配

1)从hadoop100的快照中克隆出3台虚拟机,并分配好内存

建议内存不低于4G,尤其是hadoop102,作为主机,后续可能要8G才能较顺利运行

机子建议内存
Hadoop1028G作为主节点
Hadoop1032G
Hadoop1042G

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SrNAE2gR-1598860922779)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg)]

2)原始虚拟机的已经创建好了root和user的账号&密码如下:

root: xxxxxxxx

atguigu: 123456

3)开启虚拟机

4.0.2 修改虚拟机IP (ROOT 权限下)

1)修改静态IP,

vim /etc/sysconfig/network-scripts/ifcfg-eth0

=================================

DEVICE=eth0

TYPE=Ethernet

ONBOOT=yes

BOOTPROTO=static

IPADDR=192.168.1.102

PREFIX=24

GATEWAY=192.168.1.2

DNS1=114.114.114.114

NAME=eth0

执行 service network restart 重启,查看ifconfig 是否已经更新

2)修改hostname

vim /etc/sysconfig/network

改HOSTNAME=hadoop102
分别配置其他机器

机子IPADDRHOSTNAME
Hadoop102.102hadoop102
Hadoop103.103hadoop103
Hadoop104.104hadoop104

3)修改克隆后虚拟机的ip

[root@hadoop101 /]# vim /etc/udev/rules.d/70-persistent-net.rules

进入如下页面,删除eth0该行;将eth1修改为eth0,同时复制物理ip地址,如下图所示(这步是针对Centos 6.8的,Centos 7不用此步操作)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1BaAZiTe-1598860922782)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg)]

4.0.3配置分发脚本

1)在/home/atguigu目录下创建bin目录,并在bin目录下xsync创建文件,文件内容如下:

[atguigu@hadoop102 ~]$ mkdir bin

[atguigu@hadoop102 ~]$ cd bin/

[atguigu@hadoop102 bin]$ vim  xsync

内容如下:

#!/bin/bash
#1 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if ((pcount==0)); then
echo no args;
exit;
fi

#2 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname

#3 获取上级目录到绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir

#4 获取当前用户名称
user=`whoami`

#5 循环
for((host=103; host<105; host++)); do
        echo ------------------- hadoop$host --------------
        rsync -av $pdir/$fname $user@hadoop$host:$pdir
done

2)修改执行权限

chmod +x xsync    

3)文档放在bin目录下,使其有全局运行的权限

sudo cp xsync /bin    

4)分发到集群,yes,输如其他机器的root密码

sudo xsync  /bin/xsync  
4.0.4 配置免密

哪个机子上有NameNode 或resourcemanage,即会与其他机子产生交互的,就需要配置ssh免密登陆。

生成公钥和私钥:

[atguigu@hadoop102 .ssh]$ ssh-keygen -t rsa

然后敲(三个回车),就会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)

 

将公钥拷贝到要免密登录的目标机器上

[atguigu@hadoop102 .ssh]$ ssh-copy-id hadoop102

[atguigu@hadoop102 .ssh]$ ssh-copy-id hadoop103

[atguigu@hadoop102 .ssh]$ ssh-copy-id hadoop104

注意,

还需要在hadoop103上采用atguigu账号,配置一下无密登录到hadoop102、hadoop103、hadoop104;

还需要在hadoop104上采用atguigu账号,配置一下无密登录到hadoop102、hadoop103、hadoop104服务器上。

4.0.5 JDK

1)在hadoop102,hadoop103, hadoop104安装JDK配置环境变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzMXXGL9-1598860922786)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image007.png)]

2)将JDk jar包传入,解压到 /opt/module目录下

[atguigu@hadoop102 jdk1.8.0_144]$ tar -zxvf jdk-8u144-linux-x64.tar.gz -C /opt/module/

3)获取路径

[atguigu@hadoop102 jdk1.8.0_144]$ pwd

/opt/module/jdk1.8.0_144

4)修改配置文件,注意采用新方式,这样可以避免本地或远程时总要source profile

[atguigu@hadoop102 jdk1.8.0_144]$ sudo vim /etc/profile.d/env.sh
#JAVA_HOME

export JAVA_HOME=/opt/module/jdk1.8.0_144

export PATH=$PATH:$JAVA_HOME/bin

5)source文件使之生效,并查看jdk是否成功

[atguigu@hadoop102 jdk1.8.0_144]$ source /etc/ profile.d/env.sh

[atguigu@hadoop102 jdk1.8.0_144]$ java

用法: java [-options] class [args…]

5)分发jdk

[atguigu@hadoop102 ~]$ xsync jdk1.8.0_144/

6)分发 /etc/profile文件

[atguigu@hadoop102 ~]$ sudo xsync /etc/profile.d/env.sh

Source profile文件,输入java命令看java是否成功运行

[atguigu@hadoop103 ~]$ source /etc/profile.d/env.sh

[atguigu@hadoop104 ~]$ source /etc/profile.d/env.sh

4.1 hadoop安装

4.1.0 hadoop安装配置

1)解压hadoop-2.7.2到/opt/module目录下


[atguigu@hadoop102 hadoop-2.7.2]$ pwd

/opt/module/hadoop-2.7.2

2)配置环境变量

[atguigu@hadoop102 jdk1.8.0_144]$ sudo vim /etc/profile.d/env.sh

##HADOOP_HOME

export HADOOP_HOME=/opt/module/hadoop-2.7.2

export PATH=$PATH:$HADOOP_HOME/bin

export PATH=$PATH:$HADOOP_HOME/sbin

3)source配置文件

[atguigu@hadoop102 jdk1.8.0_144]$ source /etc/ profile.d/env.sh

4)修改8个配置文件(所有配置文件都在$HADOOP_HOME/etc/hadoop中)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zVKjXbYu-1598860922788)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image009.jpg)]

5)配置hadoop-env.sh,yarn-env.sh,mapred-env.sh文件,

在每个文件第二行添加Java_HOME,

export JAVA_HOME=/opt/module/jdk1.8.0_144

6)配置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>

7) 配置hdfs-site.xml

<!-- 数据的副本数量正常配置3个副本 -->

<property>

​    <name>dfs.replication</name>

​    <value>3</value>

</property>

<!-- 指定Hadoop辅助名称节点主机配置 -->

<property>

​      <name>dfs.namenode.secondary.http-address</name>

​      <value>hadoop104:50090</value>

</property>

8) 配置yarn-site.xml

<!-- Site specific YARN configuration properties -->

<!-- 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>

<!-- 日志聚集功能使能 -->

<property>

​    <name>yarn.log-aggregation-enable</name>

​    <value>true</value>

</property>

 

<!-- 日志保留时间设置7天 -->

<property>

​    <name>yarn.log-aggregation.retain-seconds</name>

​    <value>604800</value>

</property>

9) 配置mapred-site.xml

先重命名

[atguigu@hadoop102 hadoop]$ mv mapred-site.xml.template mapred-site.xml
<!-- 指定MR运行在Yarn上 -->

<property>

​    <name>mapreduce.framework.name</name>

​    <value>yarn</value>

</property>

<!-- 历史服务器端地址 -->

<property>

​    <name>mapreduce.jobhistory.address</name>

​    <value>hadoop102:10020</value>

</property>

<!-- 历史服务器web端地址 -->

<property>

​    <name>mapreduce.jobhistory.webapp.address</name>

​    <value>hadoop102:19888</value>

</property>

​    

注:启动历史服务器命令:

mr-jobhistory-daemon.sh start historyserver

后续要开启改服务,以便更好的收集集群运行日志。

10) 配置Slaves(文件中无空格,无空行)

​    hadoop102
​    hadoop103
​    hadoop104

11)集群首次启动前必须要要格式化Namenode

 在hadoop102:bin/hdfs namenode -format

注意:除非是新集群,否则不要没事就格式化NameNode!!

因此操作会产生新的集群id,导致NameNode和DataNode的集群id不一致,集群找不到已往数据。

所以,如果后续非要格式NameNode不可,一定要先删除data数据和log日志,然后再格式化NameNode。

11)启动hadoop集群

 [atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh

 

12)启动resourcemanage (YARN服务)

[atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh
4.1.1 项目经验之HDFS 存储多目录

若HDFS 存储空间紧张,需要对DataNode 进行磁盘扩展。

1) 在DataNode 节点增加磁盘并进行挂载。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CM0gK7rl-1598860922790)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image011.jpg)]

2)在hdfs-site.xml 文件中配置多目录,注意新挂载磁盘的访问权限问题。

<property>

<name>dfs.datanode.data.dir</name>

<value>file:///${hadoop.tmp.dir}/dfs/data1,file:///hd2/dfs/data2,file:///hd3/dfs/data3,file:///hd4/dfs/data4</value>

</property>

3)增加磁盘后,保证每个目录数据均衡

开启数据均衡命令:

bin/start-balancer.sh –threshold 10

对于参数10,代表的是集群中各个节点的磁盘空间利用率相差不超过10%,可根据实际情况进行调整。

停止数据均衡命令:

bin/stop-balancer.sh
4.1.2 项目经验之支持 LZO 压缩配置

1)hadoop 本身并不支持 lzo 压缩,故需要使用 twitter 提供的 hadoop-lzo 开源组件。hadoop-lzo 需依赖 hadoop 和 lzo 进行编译,编译步骤如下。环境准备参考附录1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bo2Ni4ye-1598860922792)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image013.jpg)]

2)将编译好后的 hadoop-lzo-0.4.20.jar 放入 hadoop-2.7.2/share/hadoop/common/
在这里插入图片描述

[atguigu@hadoop102 common]$ pwd
/opt/module/hadoop-2.7.2/share/hadoop/common [atguigu@hadoop102 common]$ ls
hadoop-lzo-0.4.20.jar

3)同步 hadoop-lzo-0.4.20.jar 到 hadoop103、hadoop104

[atguigu@hadoop102 common]$ xsync hadoop-lzo-0.4.20.jar                 

4)core-site.xml 增加配置支持 LZO 压缩(仅需红色字体)

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<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>

5)同步 core-site.xml 到 hadoop103、hadoop104

[atguigu@hadoop102 hadoop]$ xsync core-site.xml 

6)启动及查看集群

[atguigu@hadoop102 hadoop-2.7.2]$ sbin/start-dfs.sh

[atguigu@hadoop103 hadoop-2.7.2]$ sbin/start-yarn.sh
4.1.3 项目经验之 LZO 创建索引

1)创建 LZO 文件的索引,LZO 压缩文件的可切片特性依赖于其索引,故我们需要手动为LZO 压缩文件创建索引。若无索引,则 LZO 文件的切片只有一个。

[atguigu@hadoop102 module]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/common/hadoop-lzo-0.4.20.jar com.hadoop.compression.lzo.DistributedLzoIndexer /input/bigtable.lzo

2)测试

(1)将bigtable.lzo(150M)上传到集群的根目录

[atguigu@hadoop102 module]$ hadoop fs -mkdir /input

[atguigu@hadoop102 module]$ hadoop fs -put bigtable.lzo /input

(2)执行wordcount 程序

[atguigu@hadoop102 module]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /input /output1

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jOl5tLM7-1598860922796)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image016.jpg)]

(3)对上传的LZO 文件建索引

[atguigu@hadoop102 module]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/common/hadoop-lzo-0.4.20.jar com.hadoop.compression.lzo.DistributedLzoIndexer /input/bigtable.lzo

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nc8qp8hA-1598860922798)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image018.jpg)]

(4)再次执行WordCount 程序

[atguigu@hadoop102 module]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /input /output2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zOXQcblE-1598860922800)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image020.jpg)]

4.1.4 项目经验之基准测试

1) 测试 HDFS 写性能

测试内容:向 HDFS 集群写 10 个 128M 的文件

[atguigu@hadoop102 mapreduce]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.2-tests.jar TestDFSIO -write -nrFiles 10 -fileSize 128MB

 

19/05/02 11:45:23 INFO fs.TestDFSIO: ----- TestDFSIO ----- : write

19/05/02 11:45:23 INFO fs.TestDFSIO: Date & time: Thu May 02 11:45:23 CST 2019

19/05/02 11:45:23 INFO fs.TestDFSIO: Number of files: 10

19/05/02 11:45:23 INFO fs.TestDFSIO: Total MBytes processed: 1280.0

19/05/02 11:45:23 INFO fs.TestDFSIO: Throughput mb/sec: 10.69751115716984 吞吐量指标

19/05/02 11:45:23 INFO fs.TestDFSIO: Average IO rate mb/sec: 14.91699504852295

19/05/02 11:45:23 INFO fs.TestDFSIO: IO rate std deviation: 11.160882132355928

19/05/02 11:45:23 INFO fs.TestDFSIO: Test exec time sec: 52.315

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-870FW8BA-1598860922801)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image022.jpg)]

2)测试 HDFS 读性能

测试内容:读取 HDFS 集群 10 个 128M 的文件

[atguigu@hadoop102 mapreduce]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.2-tests.jar TestDFSIO -read -nrFiles 10 -fileSize 128MB

 

19/05/02 11:56:36 INFO fs.TestDFSIO: ----- TestDFSIO ----- : read

19/05/02 11:56:36 INFO fs.TestDFSIO: Date & time: Thu May 02 11:56:36 CST 2019

19/05/02 11:56:36 INFO fs.TestDFSIO: Number of files: 10

19/05/02 11:56:36 INFO fs.TestDFSIO: Total MBytes processed: 1280.0

19/05/02 11:56:36 INFO fs.TestDFSIO: Throughput mb/sec: 16.001000062503905

19/05/02 11:56:36 INFO fs.TestDFSIO: Average IO rate mb/sec: 17.202795028686523

19/05/02 11:56:36 INFO fs.TestDFSIO: IO rate std deviation: 4.881590515873911

19/05/02 11:56:36 INFO fs.TestDFSIO: Test exec time sec: 49.116

19/05/02 11:56:36 INFO fs.TestDFSIO:

3)删除测试生成数据

[atguigu@hadoop102 mapreduce]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.2-tests.jar TestDFSIO -clean

4)使用 Sort 程序评测 MapReduce

(1)使用 RandomWriter 来产生随机数,每个节点运行 10 个 Map 任务,每个 Map 产 生大约 1G 大小的二进制随机数

[atguigu@hadoop102 mapreduce]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar randomwriter random-data

 

(2)执行 Sort 程序

 [atguigu@hadoop102 mapreduce]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar sort random-data sorted-data

(3)验证数据是否真正排好序了

[atguigu@hadoop102 mapreduce]$ hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-2.7.2-tests.jar testmapredsort -sortInput random-data -sortOutput sorted-data
4.1.5 项目经验之Hadoop 参数调优

1)HDFS 参数调优hdfs-site.xml

dfs.namenode.handler.count=20 * log2(Cluster Size),比如集群规模为8 台时,此参数设置为60

The number of Namenode RPC server threads that listen to requests from clients. If dfs.namenode.servicerpc-address is not configured then Namenode RPC server threads listen to requests from all nodes.

NameNode 有一个工作线程池,用来处理不同DataNode 的并发心跳以及客户端并发的元数据操作。对于大集群或者有大量客户端的集群来说,通常需要增大参数dfs.namenode.handler.count 的默认值10。设置该值的一般原则是将其设置为集群大小的自然对数乘以20,即20logN,N 为集群大小。

2)YARN 参数调优yarn-site.xml

(1)情景描述:总共7 台机器,每天几亿条数据,数据源->Flume->Kafka->HDFS->Hive

面临问题:数据统计主要用HiveSQL,没有数据倾斜,小文件已经做了合并处理,开

启的JVM 重用,而且IO 没有阻塞,内存用了不到50%。但是还是跑的非常慢,而且数据

量洪峰过来时,整个集群都会宕掉。基于这种情况有没有优化方案。

(2)解决办法:

内存利用率不够。这个一般是Yarn 的2 个配置造成的,单个任务可以申请的最大内存

大小,和Hadoop 单个节点可用内存大小。调节这两个参数能提高系统内存的利用率。

(a)yarn.nodemanager.resource.memory-mb

表示该节点上YARN 可使用的物理内存总量,默认是8192(MB),注意,如果你的节点

内存资源不够8GB,则需要调减小这个值,而YARN 不会智能的探测节点的物理内存总量。

(b)yarn.scheduler.maximum-allocation-mb

单个任务可申请的最多物理内存量,默认是8192(MB)。

3)Hadoop 宕机

(1)如果MR 造成系统宕机。此时要控制Yarn 同时运行的任务数,和每个任务申请的

最大内存。调整参数:yarn.scheduler.maximum-allocation-mb(单个任务可申请的最多物

理内存量,默认是8192MB)

(2)如果写入文件过量造成NameNode 宕机。那么调高Kafka 的存储大小,控制从Kafka到HDFS 的写入速度。高峰期的时候用Kafka 进行缓存,高峰期过去数据同步会自动跟上。

4.2 Zookeeper 安装

4.2.1 安装ZK

集群规划

服务器hadoop102服务器hadoop103服务器hadoop104
ZookeeperZookeeperZookeeperZookeeper

1.集群规划
在hadoop102、hadoop103和hadoop104三个节点上部署Zookeeper。

2.解压安装
(1)解压Zookeeper安装包到/opt/module/目录下

[atguigu@hadoop102 software]$ tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/module/

(2)同步/opt/module/zookeeper-3.4.10目录内容到hadoop103、hadoop104

[atguigu@hadoop102 module]$ xsync zookeeper-3.4.10/

3.配置服务器编号
(1)在/opt/module/zookeeper-3.4.10/这个目录下创建zkData

[atguigu@hadoop102 zookeeper-3.4.10]$ mkdir -p zkData

(2)在/opt/module/zookeeper-3.4.10/zkData目录下创建一个myid的文件

[atguigu@hadoop102 zkData]$ touch myid

添加myid文件,注意一定要在linux里面创建,在notepad++里面很可能乱码
(3)编辑myid文件

[atguigu@hadoop102 zkData]$ vi myid
在文件中添加与server对应的编号:
2

(4)拷贝配置好的zookeeper到其他机器上

[atguigu@hadoop102 zkData]$ xsync myid

并分别在hadoop103、hadoop104上修改myid文件中内容为3、4

4.配置zoo.cfg文件
(1)重命名/opt/module/zookeeper-3.4.10/conf这个目录下的zoo_sample.cfg为zoo.cfg

[atguigu@hadoop102 conf]$ mv zoo_sample.cfg zoo.cfg

(2)打开zoo.cfg文件

[atguigu@hadoop102 conf]$ vim zoo.cfg

修改数据存储路径配置

dataDir=/opt/module/zookeeper-3.4.10/zkData

增加如下配置

#######################cluster##########################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888

(3)同步zoo.cfg配置文件

[atguigu@hadoop102 conf]$ xsync zoo.cfg

(4)配置参数解读

server.A=B:C:D。

A是一个数字,表示这个是第几号服务器;
集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。
B是这个服务器的地址;
C是这个服务器Follower与集群中的Leader服务器交换信息的端口;
D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。

(5) 配置Zookeeper的LogDIR:

配置bin/zkEnv.sh文件
    ZOO_LOG_DIR="."改为/opt/module/zookeeper-3.4.10/logs

5.集群操作
(1)分别启动Zookeeper

[atguigu@hadoop102 zookeeper-3.4.10]$ bin/zkServer.sh start
[atguigu@hadoop103 zookeeper-3.4.10]$ bin/zkServer.sh start
[atguigu@hadoop104 zookeeper-3.4.10]$ bin/zkServer.sh start

(2)查看状态

[atguigu@hadoop102 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
[atguigu@hadoop103 zookeeper-3.4.10]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: leader
[atguigu@hadoop104 zookeeper-3.4.5]# bin/zkServer.sh status
JMX enabled by default
Using config: /opt/module/zookeeper-3.4.10/bin/../conf/zoo.cfg
Mode: follower
4.2.2 ZK 集群启动停止脚本

1)在hadoop102 的/home/atguigu/bin 目录下创建脚本

[atguigu@hadoop102 bin]$ vim zk.sh

在脚本中编写如下内容

#! /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

2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 zk.sh

3)Zookeeper 集群启动脚本

[atguigu@hadoop102 module]$ zk.sh start

4)Zookeeper 集群停止脚本

[atguigu@hadoop102 module]$ zk.sh stop
4.2.3 项目经验之Linux 环境变量

1)修改/etc/profile 文件:用来设置系统环境参数,比如$PATH. 这里面的环境变量是对系统内所有用户生效。使用bash 命令,需要source /etc/profile 一下。

2)修改~/.bashrc 文件:针对某一个特定的用户,环境变量的设置只对该用户自己有效。

使用bash 命令,只要以该用户身份运行命令行就会读取该文件。

3)把/etc/profile 里面的环境变量追加到~/.bashrc 目录

[atguigu@hadoop102 ~]$ cat /etc/profile >> ~/.bashrc

[atguigu@hadoop103 ~]$ cat /etc/profile >> ~/.bashrc

[atguigu@hadoop104 ~]$ cat /etc/profile >> ~/.bashrc

4)说明

登录式Shell,采用用户名比如atguigu 登录,会自动加载/etc/profile

非登录式Shell,采用ssh 比如ssh hadoop103 登录,不会自动加载/etc/profile,会自动加载~/.bashrc

[atguigu@hadoop102 ~]$ vim .bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

# User specific aliases and functions

[atguigu@hadoop102 ~]$ vim /etc/bashrc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ASY9H5T-1598860922804)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image023.png)]

可以看到会遍历执行/ect/profile.d/下的sh命令,而我们前面的环境变量就是配置在profile.d/下的,这样会更专业!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yFOP8juH-1598860922806)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image024.png)]

4.3 日志生成

4.3.1 日志启动

1)代码参数说明

// 参数一:控制发送每条的延时时间,默认是0

Long delay = args.length > 0 ? Long.parseLong(args[0]) : 0L;

// 参数二:循环遍历次数

int loop_len = args.length > 1 ? Integer.parseInt(args[1]) : 1000;

2 ) 将生成的jar 包log-collector-0.0.1-SNAPSHOT-jar-with-dependencies.jar 拷贝到hadoop102 服务器/opt/module 上,并同步到hadoop103 的/opt/module 路径下,

[atguigu@hadoop102 module]$ xsync log-collector-1.0-SNAPSHOT-jar-with-dependencies.jar

3)在hadoop102 上执行jar 程序

[atguigu@hadoop102 module]$ java -classpath log-collector-1.0-SNAPSHOT-jar-with-dependencies.jar com.atguigu.appclient.AppMain >/opt/module/test.log

说明1:

java -classpath 需要在jar 包后面指定全类名;

java -jar 需要查看一下解压的jar 包META-INF/ MANIFEST.MF 文件中,Main-Class 是否有全类名。如果有可以用java -jar,如果没有就需要用到java -classpath

在这里插入图片描述

已经在创建Maven是打包好了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GzOlFulK-1598860922816)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image032.jpg)]

说明2:/dev/null 代表linux 的空设备文件,所有往这个文件里面写入的内容都会丢失,俗称“黑洞”。

标准输入0:从键盘获得输入/proc/self/fd/0

标准输出1:输出到屏幕(即控制台) /proc/self/fd/1

错误输出2:输出到屏幕(即控制台) /proc/self/fd/2

[atguigu@hadoop102 module]$ java -classpath log-collector-1.0-SNAPSHOT-jar-with-dependencies.jar com.atguigu.appclient.AppMain >/dev/null 2>&1

或者

[atguigu@hadoop102 module]$ java -classpath log-collector-1.0-SNAPSHOT-jar-with-dependencies.jar com.atguigu.appclient.AppMain 1>dev/null 2>/dev/null

4)在/tmp/logs 路径下查看生成的日志文件

[atguigu@hadoop102 module]$ cd /tmp/logs/

[atguigu@hadoop102 logs]$ ls app-2020-03-10.log
4.3.2 集群日志生成启动脚本

1)在/home/atguigu/bin 目录下创建脚本lg.sh

[atguigu@hadoop102 bin]$ vim lg.sh

2)在脚本中编写如下内容

#! /bin/bash
for i in hadoop102 hadoop103
do
echo ---------------$i 生成日志----------------
ssh $i "java -classpath /opt/module/log-collector-1.0-SNAPSHOT-jar-with-dependencies.jar com.atguigu.appclient.AppMain $1 $2 >/dev/null 2>&1 &"
done

# &1 ,&2 是两个参数 ,末尾的&是保持后台运行

# &1 ,&2 是两个参数 ,末尾的&是保持后台运行

3)修改脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 lg.sh

4)启动脚本

[atguigu@hadoop102 module]$ lg.sh

5)分别在hadoop102、hadoop103 的/tmp/logs 目录上查看生成的数据

[atguigu@hadoop102 logs]$ ls app-2020-03-10.log

[atguigu@hadoop103 logs]$ ls app-2020-03-10.log
4.3.3 集群时间同步修改脚本(非正规临时脚本)

企业开发时,参考hadoop 集群时间同步。

1)在/home/atguigu/bin 目录下创建脚本dt.sh

[atguigu@hadoop102 bin]$ vim dt.sh

2)在脚本中编写如下内容

#!/bin/bash
for i in hadoop102 hadoop103 hadoop104
do
echo "========== $i 同步时间=========="
ssh -t $i "sudo date -s $1"
done

注意:ssh -t 通常用于ssh 远程执行sudo 命令

3)修改脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 dt.sh

4)启动脚本

[atguigu@hadoop102 bin]$ dt.sh 2020-03-10
4.3.4 集群所有进程查看脚本

1)在/home/atguigu/bin 目录下创建脚本xcall.sh

[atguigu@hadoop102 bin]$ vim xcall.sh

2)在脚本中编写如下内容

#! /bin/bash
for i in hadoop102 hadoop103 hadoop104
do
echo --------- $i ----------
ssh $i "$*"
done

#$*传入的参数全部执行

3)修改脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 xcall.sh

4)启动脚本

[atguigu@hadoop102 bin]$ xcall.sh jps

 

4.4 采集日志Flume

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yfu5a8G1-1598860922818)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image034.png)]

集群规划:

服务器hadoop102服务器hadoop103服务器hadoop104
Flume(采集日志)FlumeFlume

Flume的安装部署
1)将apache-flume-1.7.0-bin.tar.gz上传到linux的/opt/software目录下

2)解压apache-flume-1.7.0-bin.tar.gz到/opt/module/目录下

[atguigu@hadoop102 software]$ tar -zxf apache-flume-1.7.0-bin.tar.gz -C /opt/module/

3)修改apache-flume-1.7.0-bin的名称为flume

[atguigu@hadoop102 module]$ mv apache-flume-1.7.0-bin flume

4) 将flume/conf下的flume-env.sh.template文件修改为flume-env.sh,并配置flume-env.sh文件

[atguigu@hadoop102 conf]$ mv flume-env.sh.template flume-env.sh
[atguigu@hadoop102 conf]$ vi flume-env.sh
Echo $JAVA_HOME显示Java_home路径,拷贝
export JAVA_HOME=/opt/module/jdk1.8.0_144

5)分发

4.4.2 项目经验之Flume 组件

1)Source

(1)Taildir Source 相比Exec Source、Spooling Directory Source 的优势

TailDir Source:断点续传、多目录。Flume1.6 以前需要自己自定义Source 记录每次读取文件位置,实现断点续传。

Exec Source 可以实时搜集数据,但是在Flume 不运行或者Shell 命令出错的情况下,数据将会丢失。

Spooling Directory Source 监控目录,不支持断点续传。

(2)batchSize 大小如何设置?

答:Event 1K 左右时,500-1000 合适(默认为100)

2)Channel

**采用Kafka Channel,省去了Sink,提高了效率。KafkaChannel 数据存储在**Kafka 里面,所以数据是存储在磁盘中。

注意在Flume1.7 以前,Kafka Channel 很少有人使用,因为发现parseAsFlumeEvent 这个配置起不了作用。也就是无论parseAsFlumeEvent 配置为true 还是false,都会转为Flume Event。这样的话,造成的结果是,会始终都把Flume 的headers 中的信息混合着内容一起写入Kafka的消息中,这显然不是我所需要的,我只是需要把内容写入即可。

4.4.3 日志采集Flume 配置

1)Flume 配置分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lJOmrlpK-1598860922819)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image038.png)]

Flume 直接读log 日志的数据,log 日志的格式是app-yyyy-mm-dd.log。

2)Flume 的具体配置如下:

(1)在/opt/module/flume/conf 目录下创建file-flume-kafka.conf 文件

[atguigu@hadoop102 conf]$ vim file-flume-kafka.conf

在文件配置如下内容

a1.sources=r1
a1.channels=c1 c2

# configure source
a1.sources.r1.type = TAILDIR
a1.sources.r1.positionFile =/opt/module/flume/test/log_position.json
a1.sources.r1.filegroups = f1
#app.+ 正则,表示app开头的都匹配
a1.sources.r1.filegroups.f1 = /tmp/logs/app.+
a1.sources.r1.fileHeader = true
a1.sources.r1.channels = c1 c2

#interceptor
a1.sources.r1.interceptors = i1 i2
a1.sources.r1.interceptors.i1.type =com.atguigu.flume.interceptor.LogETLInterceptor$Builder
a1.sources.r1.interceptors.i2.type =com.atguigu.flume.interceptor.LogTypeInterceptor$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

# configure channel
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.c1.kafka.consumer.group.id = flume-consumer
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.channels.c2.kafka.consumer.group.id = flume-consumer

注意:com.atguigu.flume.interceptor.LogETLInterceptor 和com.atguigu.flume.interceptor.LogTypeInterceptor 是自定义的拦截器的全类名。需要根据用户自定义的拦截器做相应修改

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qkeONdsL-1598860922821)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image040.png)]

4.4.4 Flume 的ETL 和分类型拦截器

本项目中自定义了两个拦截器,分别是:ETL 拦截器、日志类型区分拦截器。

ETL 拦截器主要用于,过滤时间戳不合法和Json 数据不完整的日志

日志类型区分拦截器主要用于,将启动日志和事件日志区分开来,方便发往Kafka 的不同Topic。

自定义拦截器步骤:

  1. 定义一个类,实现Interceptor接口
  2. 重写4个方法
    初始化
    单event
    Event能获取到body header
    ETL =>body=> 主要判断的就是json数据是否已{开头,以}结尾 服务器时间(长度13,且全部为数字)
    分类型拦截器=> body, header => 根据body区分类型,把相应数据添加到头里面 topic, start_topic/ event_topic
    多event
    关闭资源
  3. 静态内部类
  4. 打包上传

1)创建Maven 工程flume-interceptor

2)创建包名:com.atguigu.flume.interceptor

3)在pom.xml 文件中添加如下配置

<dependencies>
    <dependency>
        <groupId>org.apache.flume</groupId>
        <artifactId>flume-ng-core</artifactId>
        <version>1.7.0</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

4)在com.atguigu.flume.interceptor 包下创建LogETLInterceptor 类名

Flume ETL 拦截器LogETLInterceptor

package com.atguigu.flume.interceptor;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

public class LogETLInterceptor implements Interceptor {
    //初始化
    @Override
    public void initialize() {

    }

    //单Event处理
    @Override
    public Event intercept(Event event) {

        //清洗数据  ETL 去除脏数据
        //{"action":"1","ar":"MX","ba":"HTC","d
        //1.获取日志
        byte[] body = event.getBody();
        String log = new String(body, Charset.forName("UTF-8"));


        //2.区分类型处理
        if (log.contains("start")){
            //验证启动日志的逻辑
            if (LogUtils.validateStart(log)){
                return event;
            }
        }else{
            //验证事件日志的逻辑
            if (LogUtils.validateEvent(log)){
                return event;
            }
        }

        return null;

    }

    //多event处理
    @Override
    public List<Event> intercept(List<Event> events) {

        ArrayList<Event> interceptors = new ArrayList<>();

        //取出校验合格的数据并返回
        for (Event event : events) {
            Event intercept1 = intercept(event);

            if (intercept1 != null){
                interceptors.add(intercept1);
            }
        }

        return interceptors;
    }

    //关闭资源
    @Override
    public void close() {

    }

    public static class Builder implements Interceptor.Builder{
        @Override
        public Interceptor build() {
            return new LogETLInterceptor();
        }

        @Override
        public void configure(Context context) {

        }
    }
}

4)Flume 日志过滤工具类

package com.atguigu.flume.interceptor;

import org.apache.commons.lang.math.NumberUtils;

public class LogUtils {

    //验证启动日志
    public static boolean validateStart(String log) {

        //{"action":"1","ar":"MX","ba":"HTC","detail":"325","en":"start","}
        if (log == null){
            return false;
        }
        //判断数据是否是{开头 是否是}结尾
        if (!log.trim().startsWith("{") || !log.trim().endsWith("}")){
            return false;
        }
        return true;
    }

    //验证事件日志
    // {"action":"1","ar":"MX","ba":"HTC","detail":"325","en":"start
    public static boolean validateEvent(String log) {
        //服务器事件|日志内容

        if ( log == null){
            return false;
        }
        //切割
        String[] logContents = log.split("\\|");//正则里用\|表示|,故再加上\表示转义。。

        if (logContents.length != 2){
            return false;
        }
        //校验服务器时间(长度必须是13位,必须全部是数字
        if (logContents[0].length()!= 13 || !NumberUtils.isDigits(logContents[0])){
            return false;
        }

        //校验日志格式
        if (!logContents[1].trim().startsWith("{") || !logContents[1].trim().endsWith("}")){
            return false;
        }

        return true;
    }
}

5) Flume 日志类型区分拦截器LogTypeInterceptor

6package com.atguigu.flume.interceptor;

import org.apache.flume.Context;
import org.apache.flume.Event;
import org.apache.flume.interceptor.Interceptor;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class LogTypeInterceptor implements Interceptor {
    @Override
    public void initialize() {

    }

    @Override
    public Event intercept(Event event) {

        //区分类型 Start event
        //body header
        //获取body
        byte[] body = event.getBody();
        String log = new String(body, Charset.forName("UTF-8"));

        //获取头信息
        Map<String, String> headers = event.getHeaders();

        //业务逻辑判断
        if (log.contains("start")){

            headers.put("topic","topic_start" );//不产生新对象

        }else{
            headers.put("topic","topic_event" );
        }

        return event;
    }

    @Override
    public List<Event> intercept(List<Event> events) {

        ArrayList<Event> interceptors = new ArrayList<>();

        for (Event event : events) {

            Event intercept1 = intercept(event);

            interceptors.add(intercept1);

        }
        return interceptors;
    }

    @Override
    public void close() {

    }

    public static class Builder implements Interceptor.Builder{
        @Override
        public Interceptor build() {
            return new LogTypeInterceptor();
        }

        @Override
        public void configure(Context context) {

        }
    }
}

6)打包

拦截器打包之后,只需要单独包,不需要将依赖的包上传。打包之后要放入Flume 的

lib 文件夹下面。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g5C83HoQ-1598860922823)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image042.jpg)]

注意:为什么不需要依赖包?因为依赖包在flume 的lib 目录下面已经存在了。

7)需要先将打好的包放入到hadoop102 的/opt/module/flume/lib 文件夹下面。

[atguigu@hadoop102 lib]$ ls | grep interceptor flume-interceptor-1.0-SNAPSHOT.jar

8)分发Flume 到hadoop103、hadoop104

[atguigu@hadoop102 module]$ xsync flume/
[atguigu@hadoop102 flume]$ bin/flume-ng agent --name a1 --conf-file conf/file-flume-kafka.conf &
4.4.5 日志采集Flume 启动停止脚本

1)在/home/atguigu/bin 目录下创建脚本f1.sh

[atguigu@hadoop102 bin]$ vim f1.sh

在脚本中填写如下内容

#! /bin/bash
case $1 in
"start"){
for i in hadoop102 hadoop103
do
echo " --------启动$i 采集flume-------"
ssh $i "nohup /opt/module/flume/bin/flume-ng agent --conf-file /opt/module/flume/conf/file-flume-kafka.conf --name a1 -Dflume.root.logger=INFO,LOGFILE >/opt/module/flume/test1 2>&1 &" 
done
};;
"stop"){
for i in hadoop102 hadoop103
do
echo " --------停止$i 采集flume-------"
ssh $i "ps -ef | grep file-flume-kafka | grep -v grep |awk '{print \$2}' | xargs kill"
done
};;
esac

说明1:nohup,该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。nohup

就是不挂起的意思,不挂断地运行命令。

说明2:awk 默认分隔符为空格 {print $2},\表示awk的参数,转义

说明3:xargs 表示取出前面命令运行的结果,作为后面命令的输入参数。

2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 f1.sh

3)f1 集群启动脚本

[atguigu@hadoop102 module]$ f1.sh start

4)f1 集群停止脚本

[atguigu@hadoop102 module]$ f1.sh stop

4.5 Kafka 安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a91tMu55-1598860922825)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image044.png)]

4.5.1 Kafka 集群安装

集群规划:

服务器hadoop102服务器hadoop103服务器hadoop104
KafkaKafkaKafkaKafka

集群部署
1)解压安装包

[atguigu@hadoop102 software]$ tar -zxvf kafka_2.11-0.11.0.0.tgz -C /opt/module/

2)修改解压后的文件名称

[atguigu@hadoop102 module]$ mv kafka_2.11-0.11.0.0/ kafka

3)在/opt/module/kafka目录下创建logs文件夹

[atguigu@hadoop102 kafka]$ mkdir logs

4)修改配置文件

[atguigu@hadoop102 kafka]$ cd config/
[atguigu@hadoop102 config]$ vi server.properties

输入以下内容:

#broker的全局唯一编号,不能重复
broker.id=0
#删除topic功能使能
delete.topic.enable=true
#处理网络请求的线程数量
num.network.threads=3
#用来处理磁盘IO的现成数量
num.io.threads=8
#发送套接字的缓冲区大小
socket.send.buffer.bytes=102400
#接收套接字的缓冲区大小
socket.receive.buffer.bytes=102400
#请求套接字的缓冲区大小
socket.request.max.bytes=104857600
#kafka运行日志存放的路径	
log.dirs=/opt/module/kafka/logs
#topic在当前broker上的分区个数
num.partitions=1
#用来恢复和清理data下数据的线程数量
num.recovery.threads.per.data.dir=1
#segment文件保留的最长时间,超时将被删除
log.retention.hours=168
#配置连接Zookeeper集群地址
zookeeper.connect=hadoop102:2181,hadoop103:2181,hadoop104:2181

5)配置环境变量

[atguigu@hadoop102 module]$ sudo vi /etc/profile.d/env.sh


#KAFKA_HOME
export KAFKA_HOME=/opt/module/kafka
export PATH=$PATH:$KAFKA_HOME/bin

[atguigu@hadoop102 module]$ source /etc/profile.d/env.sh

6)分发安装包

[atguigu@hadoop102 module]$ xsync kafka/
**注意:分发之后记得配置其他机器的环境变量 source**

7)分别在hadoop103和hadoop104上修改配置文件/opt/module/kafka/config/server.properties中的broker.id=1broker.id=2
注:broker.id不得重复
7-1)启动zookeeper

[atguigu@hadoop102 zookeeper-3.4.10]$ bin/zkServer.sh start

8)启动集群
依次在hadoop102、hadoop103、hadoop104节点上启动kafka

[atguigu@hadoop102 kafka]$ bin/kafka-server-start.sh -daemon config/server.properties
[atguigu@hadoop103 kafka]$ bin/kafka-server-start.sh -daemon  config/server.properties
[atguigu@hadoop104 kafka]$ bin/kafka-server-start.sh -daemon  config/server.properties

9)关闭集群

[atguigu@hadoop102 kafka]$ bin/kafka-server-stop.sh stop
[atguigu@hadoop103 kafka]$ bin/kafka-server-stop.sh stop
[atguigu@hadoop104 kafka]$ bin/kafka-server-stop.sh stop
4.5.2 Kafka 集群启动停止脚本

1)在/home/atguigu/bin 目录下创建脚本kf.sh

[atguigu@hadoop102 bin]$ vim kf.sh

在脚本中填写如下内容

#! /bin/bash
case $1 in
"start"){
for i in hadoop102 hadoop103 hadoop104
do
echo " --------启动$i Kafka-------"
ssh $i "/opt/module/kafka/bin/kafka-server-start.sh -daemon /opt/module/kafka/config/server.properties "
done
};;
"stop"){
for i in hadoop102 hadoop103 hadoop104
do
echo " --------停止$i Kafka-------"
ssh $i "/opt/module/kafka/bin/kafka-server-stop.sh stop"
done
};;
esac

2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 kf.sh

3)kf 集群启动脚本

[atguigu@hadoop102 module]$ kf.sh start

4)kf 集群停止脚本

[atguigu@hadoop102 module]$ kf.sh stop
4.5.3 查看Kafka Topic 列表
[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --zookeeper hadoop102:2181 --list
4.5.4 创建Kafka Topic

进入到/opt/module/kafka/目录下分别创建:启动日志主题、事件日志主题。

1)创建启动日志主题

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh –zookeeper hadoop102:2181,hadoop103:2181,hadoop104:2181 –create --replication-factor 1 --partitions 1 --topic topic_start

2)创建事件日志主题

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh –zookeeper hadoop102:2181,hadoop103:2181,hadoop104:2181 –create --replication-factor 1 --partitions 1 --topic topic_event
4.5.5 删除Kafka Topic

1)删除启动日志主题

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh –delete --zookeeper hadoop102:2181,hadoop103:2181,hadoop104:2181 --topic topic_start

2)删除事件日志主题

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh –delete --zookeeper hadoop102:2181,hadoop103:2181,hadoop104:2181 --topic topic_event
4.5.6 Kafka 生产消息
[atguigu@hadoop102 kafka]$ bin/kafka-console-producer.sh --broker-list hadoop102:9092 --topic topic_start


\>hello world

\>atguigu atguigu
4.5.7 Kafka 消费消息
[atguigu@hadoop102 kafka]$ bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --from-beginning --topic topic_start

 

[atguigu@hadoop102 kafka]$ bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --from-beginning --topic topic_event

–from-beginning:会把主题中以往所有的数据都读取出来。根据业务场景选择是否增加该配置。

4.5.8 查看Kafka Topic 详情
[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh –zookeeper hadoop102:2181 \

--describe --topic topic_start

**排错小技巧

\1. 先查看kafka中个的Topic,是否有我们需要的

\2. 如果有,直接消费对应的消息, 如果没有,尝试重启flume在查看topic

\3. 一般自定义interceptor会出问题,必要时检查自己写的程序。

一定要先起zookeeper,后起kafka

先关zookeeper的时候,kafka无法温柔关闭,只能强杀进程 kill -9 [进程号]

4.5.9 项目经验之Kafka 压力测试

1)Kafka 压测

用Kafka 官方自带的脚本,对Kafka 进行压测。Kafka 压测时,可以查看到哪个地方出

现了瓶颈(CPU,内存,网络IO)。一般都是网络IO 达到瓶颈。

kafka-consumer-perf-test.sh

kafka-producer-perf-test.sh

2)Kafka Producer 压力测试

(1)在/opt/module/kafka/bin 目录下面有这两个文件。我们来测试一下

[atguigu@hadoop102 kafka]$ bin/kafka-producer-perf-test.sh --topic test --record-size 100 --num-records 100000 --throughput -1 --producer-props bootstrap.servers=hadoop102:9092,hadoop103:9092,hadoop104:9092

说明:

record-size 是一条信息有多大,单位是字节。

num-records 是总共发送多少条信息。

throughput 是每秒多少条信息,设成-1,表示不限流,可测出生产者最大吞吐量。

(2)Kafka 会打印下面的信息

别人家的电脑

100000 records sent, 95877.277085 records/sec (**9.14 MB/sec**),187.68 ms avg latency, 424.00 ms max latency, 155 ms 50th, 411 ms95th, 423 ms 99th, 424 ms 99.9th.

 

我的电脑

100000 records sent, 57273.768614 records/sec (5.46 MB/sec), 589.37 ms avg latency, 893.00 ms max latency, 626 ms 50th, 875 ms 95th, 889 ms 99th, 892 ms 99.9th

参数解析:本例中一共写入10w 条消息,吞吐量为9.14 MB/sec,每次写入的平均延迟

为187.68 毫秒,最大的延迟为424.00 毫秒。

3)Kafka Consumer 压力测试

Consumer 的测试,如果这四个指标(IO,CPU,内存,网络)都不能改变,考虑增加

分区数来提升性能。

[atguigu@hadoop102 kafka]$ bin/kafka-consumer-perf-test.sh --zookeeper hadoop102:2181 --topic test --fetch-size 10000 --messages 10000000 --threads 1

参数说明:

–zookeeper 指定zookeeper 的链接信息

–topic 指定topic 的名称

–fetch-size 指定每次fetch 的数据的大小

–messages 总共要消费的消息个数

测试结果说明:

别人家电脑

start.time, **end.time,** data.consumed.in.MB, **MB.sec,** data.consumed.in.nMsg**, nMsg.sec**

2019-02-19 20:29:07:566, **2019-02-19 20:29:12:170,** 9.5368, **2.0714,** 100010, **21722.4153**

开始测试时间,测试结束数据,共消费数据9.5368MB,吞吐量**2.0714MB/s**,共消费

100010 条,平均每秒消费**21722.4153** 条。_

我的电脑

start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec

2020-03-10 01:24:46:109, 2020-03-10 01:24:49:266, 19.0735, 6.0416, 200000, 63351.2829
4.5.10 项目经验之Kafka 机器数量计算

Kafka 机器数量(经验公式)=2*(峰值生产速度*副本数/100)+1

先拿到峰值生产速度,再根据设定的副本数,就能预估出需要部署Kafka 的数量。

比如我们的峰值生产速度是50M/s。副本数为2。

Kafka 机器数量=2*(50*2/100)+ 1=3 台

如果峰值生产速度大于 50 M/s,则要考虑增加kafka机器数量

4.6 消费Kafka 数据Flume

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wz2hdgW8-1598860922826)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image046.png)]

集群规划

服务器hadoop102服务器hadoop103服务器hadoop104
Flume(消费Kafka)Flume
4.6.1 日志消费Flume 配置

1)Flume 配置分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AYLCJd6e-1598860922828)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image048.png)]

2)Flume 的具体配置如下:

(1)在hadoop104 的/opt/module/flume/conf 目录下创建kafka-flume-hdfs.conf 文件

[atguigu@hadoop104 conf]$ vim kafka-flume-hdfs.conf

在文件配置如下内容,注意单条配置没写完不要回车换行,建议在notepad++里查看

尽量把中文注解删掉后拷贝进配置文件,避免产生一些莫名其妙的错误。

## 组件
## 组件
a1.sources=r1 r2
a1.channels=c1 c2
a1.sinks=k1 k2

## source1
a1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
##5000条数据当一个批次
a1.sources.r1.batchSize = 5000
##2秒钟来一个批次与上面的协作
a1.sources.r1.batchDurationMillis = 2000
a1.sources.r1.kafka.bootstrap.servers =hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.sources.r1.kafka.topics=topic_start

## source2
a1.sources.r2.type = org.apache.flume.source.kafka.KafkaSource
a1.sources.r2.batchSize = 5000
a1.sources.r2.batchDurationMillis = 2000
a1.sources.r2.kafka.bootstrap.servers =hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.sources.r2.kafka.topics=topic_event

## channel1
a1.channels.c1.type = file
a1.channels.c1.checkpointDir =/opt/module/flume/checkpoint/behavior1
a1.channels.c1.dataDirs = /opt/module/flume/data/behavior1/
a1.channels.c1.maxFileSize = 2146435071
a1.channels.c1.capacity = 1000000
a1.channels.c1.keep-alive = 6

## channel2
a1.channels.c2.type = file
a1.channels.c2.checkpointDir =/opt/module/flume/checkpoint/behavior2
a1.channels.c2.dataDirs = /opt/module/flume/data/behavior2/
a1.channels.c2.maxFileSize = 2146435071
##file channels 能存1百万个events VS memory channel 最大100个events
a1.channels.c2.capacity = 1000000
##flume put事务的数据存活的时间,超过就把数据退了,然后再从kafka重新取
a1.channels.c2.keep-alive = 6

## sink1
a1.sinks.k1.type = hdfs
##每天一个文件夹
a1.sinks.k1.hdfs.path =/origin_data/gmall/log/topic_start/%Y-%m-%d
a1.sinks.k1.hdfs.filePrefix = logstart-

##sink2
a1.sinks.k2.type = hdfs
a1.sinks.k2.hdfs.path =/origin_data/gmall/log/topic_event/%Y-%m-%d
a1.sinks.k2.hdfs.filePrefix = logevent-

## 不要产生大量小文件,flume到hdfs里面,空值落盘文件的大小,一小时|128M先到先滚
a1.sinks.k1.hdfs.rollInterval = 3600
a1.sinks.k1.hdfs.rollSize = 134217728
a1.sinks.k1.hdfs.rollCount = 0

a1.sinks.k2.hdfs.rollInterval = 3600
a1.sinks.k2.hdfs.rollSize = 134217728
a1.sinks.k2.hdfs.rollCount = 0

## 控制输出文件是原生文件。
a1.sinks.k1.hdfs.fileType = CompressedStream
a1.sinks.k2.hdfs.fileType = CompressedStream
a1.sinks.k1.hdfs.codeC = lzop
a1.sinks.k2.hdfs.codeC = lzop
## 拼装
a1.sources.r1.channels = c1
a1.sinks.k1.channel= c1
a1.sources.r2.channels = c2
a1.sinks.k2.channel= c2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mDX7oEx0-1598860922831)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image050.jpg)]

4.6.2 项目经验之Flume 组件

1)FileChannel 和MemoryChannel 区别

MemoryChannel 传输数据速度更快,但因为数据保存在JVM 的堆内存中,Agent 进程

挂掉会导致数据丢失,适用于对数据质量要求不高的需求。

FileChannel 传输速度相对于Memory 慢,但数据安全保障高,Agent 进程挂掉也可以从失败中恢复数据。

选型:

金融类公司、对钱要求非常准确的公司通常会选择FileChannel

传输的是普通日志信息(京东内部一天丢100 万-200 万条,这是非常正常的),通常选择MemoryChannel。

2)FileChannel 优化

通过配置dataDirs 指向多个路径,每个路径对应不同的硬盘,增大Flume 吞吐量。

官方说明如下:

Comma separated list of directories for storing log files. Using

multiple directories on separate disks can improve file channel

peformance

checkpointDir 和backupCheckpointDir 也尽量配置在不同硬盘对应的目录中,保证checkpoint 坏掉后,可以快速使用backupCheckpointDir 恢复数据

3)Sink:HDFS Sink

(1)HDFS 存入大量小文件,有什么影响?

**元数据层面:**每个小文件都有一份元数据,其中包括文件路径,文件名,所有者,所属

组,权限,创建时间等,这些信息都保存在Namenode 内存中。所以小文件过多,会占用Namenode 服务器大量内存,影响Namenode 性能和使用寿命(Namenode通常存9亿个)

**计算层面:**默认情况下MR 会对每个小文件启用一个Map 任务计算,非常影响计算性

能。同时也影响磁盘寻址时间。

(2)HDFS 小文件处理

官方默认的这三个参数配置写入HDFS 后会产生小文件,hdfs.rollInterval、hdfs.rollSize、hdfs.rollCount

基于以上hdfs.rollInterval=3600,hdfs.rollSize=134217728,hdfs.rollCount =0 几个参数综合作用,效果如下:

(1)文件在达到128M 时会滚动生成新文件

(2)文件创建超3600 秒时会滚动生成新文件

4.6.3 日志消费Flume 启动停止脚本

1)在/home/atguigu/bin 目录下创建脚本f2.sh

[atguigu@hadoop102 bin]$ vim f2.sh

在脚本中填写如下内容

#! /bin/bash
case $1 in
"start"){
for i in hadoop104
do
echo " --------启动$i 消费flume-------"
ssh $i "nohup /opt/module/flume/bin/flume-ng agent --conf-file /opt/module/flume/conf/kafka-flume-hdfs.conf –name a1 -Dflume.root.logger=INFO,LOGFILE >/opt/module/flume/log.txt 2>&1 &"
done
};;
"stop"){
for i in hadoop104
do
echo " --------停止$i 消费flume-------"
ssh $i "ps -ef | grep kafka-flume-hdfs | grep -v grep |awk '{print \$2}' | xargs kill"
done
};;
esac

2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 f2.sh

3)f2 集群启动脚本

[atguigu@hadoop102 module]$ f2.sh start

4)f2 集群停止脚本

[atguigu@hadoop102 module]$ f2.sh stop

查看日志落盘情况

日志生成

[atguigu@hadoop102 bin]$ cd /tmp/logs/

[atguigu@hadoop102 logs]$ ll

-rw-rw-r--. 1 atguigu atguigu 1360231 3月  10 01:08 app-2020-03-10.log

[atguigu@hadoop102 logs]$ rm -rf app-2020-03-10.log

 

[atguigu@hadoop102 logs]$ lg.sh

在HDFS的目录下,应该能看到日志已经存储中。

/origin_data/gmall/log/topic_start/%Y-%m-%d

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TogBh7bQ-1598860922832)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image052.jpg)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l4cd2Ht8-1598860922833)(file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtmlclip1/01/clip_image054.jpg)]

如果没有打通数据流,大概率是 Flume 的conf文件没有写对(当拷贝别处的代码过来是,一定要注意是否拷贝了多余的换行符!!!)

另如果lzo.tmp的tmp后缀迟迟不消失,可以修改a1.sinks.k1.hdfs.rollInterval = 3600

把参数较小,加速其落盘;

或者可以直接关闭flume进程,这样也会强制数据flush,完成数据落盘写入。。

4.6.4 项目经验之Flume 内存优化

1)问题描述:如果启动消费Flume 抛出如下异常

ERROR hdfs.HDFSEventSink: process failed

java.lang.OutOfMemoryError: GC overhead limit exceeded

2)解决方案步骤:

(1)在hadoop102 服务器的/opt/module/flume/conf/flume-env.sh 文件中增加如下配置

export JAVA_OPTS="-Xms100m -Xmx2000m -Dcom.sun.management.jmxremote"

(2)同步配置到hadoop103、hadoop104 服务器

[atguigu@hadoop102 conf]$ xsync flume-env.sh

3)Flume 内存参数设置及优化

JVM heap 一般设置为4G 或更高,部署在单独的服务器上(4 核8 线程16G 内存)

-Xmx 与-Xms 最好设置一致,减少内存抖动带来的性能影响,如果设置不一致容易导致频繁fullgc。

-Xms 表示JVM Heap(堆内存)最小尺寸,初始分配;

-Xmx 表示JVM Heap(堆内存)最大允许的尺寸,按需分配。

如果不设置一致,容易在初始化时,由于内存不够,频繁触发fullgc。建议设置到4 到 6G,如果还是.OutofMemoryError,建议增加机器数量。

4.7 采集通道启动/停止脚本

1)在/home/atguigu/bin 目录下创建脚本cluster.sh

[atguigu@hadoop102 bin]$ vim cluster.sh

在脚本中填写如下内容

#!/bin/bash
case $1 in
"start"){
echo " -------- 启动集群-------"
echo " -------- 启动hadoop 集群-------"
/opt/module/hadoop-2.7.2/sbin/start-dfs.sh
ssh hadoop103 "/opt/module/hadoop-2.7.2/sbin/start-yarn.sh"
#启动Zookeeper 集群
zk.sh start
sleep 10s;
#启动Flume 采集集群
f1.sh start
#启动Kafka 采集集群
kf.sh start
# Kafka重型框架,启动,关闭都比较慢,因此需要睡一下
sleep 15s;
#启动Flume 消费集群
f2.sh start
};;
"stop"){
echo " -------- 停止集群-------"
#停止Flume 消费集群
f2.sh stop
#停止Kafka 采集集群
kf.sh stop
sleep 6s;
#停止Flume 采集集群
f1.sh stop
#停止Zookeeper 集群
zk.sh stop
echo " -------- 停止hadoop 集群-------"
ssh hadoop103 "/opt/module/hadoop-2.7.2/sbin/stop-yarn.sh"
/opt/module/hadoop-2.7.2/sbin/stop-dfs.sh
};;
esac

2)增加脚本执行权限

[atguigu@hadoop102 bin]$ chmod 777 cluster.sh

3)cluster集群启动脚本

[atguigu@hadoop102 module]$ cluster.sh start

4)cluster集群停止脚本

[atguigu@hadoop102 module]$ cluster.sh stop

注意:

对于此项目,如果要用dt.sh 修改时间,并用lg.sh生成伪造日期的数据,

记住要先停止集群,完成修改时间操作后,再重新启动集群。

然后再生成数据lg.sh

mp的tmp后缀迟迟不消失,可以修改a1.sinks.k1.hdfs.rollInterval = 3600

把参数较小,加速其落盘;

或者可以直接关闭flume进程,这样也会强制数据flush,完成数据落盘写入。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值