准备服务器
设置host
如果本地集群 16G 8、3、3 其他随意 8、4、4
以下为阿里云为主 本地需要设置本机host、防火墙和网络
我选的3台 阿里云服务器 每台2核8G 带宽100M拉满 按量计费便宜
配置host 需要用私网
shell远程登入用公网 密码为复杂密码
机器名称设置为正则表达式 hadoop[102,3]
不需要关闭防火墙 、网络
以下配置三台都要做!!!建个用户 赋予权限 免密登入
[root@hadoop103 ~]# vim /etc/hosts
172.24.143.121 hadoop102 hadoop102
172.24.143.122 hadoop103
172.24.143.120 hadoop104
sudo权限
[root@hadoop104 ~]# sudo useradd vanas
[root@hadoop104 ~]# sudo passwd vanas
更改用户 vanas 的密码 。
新的 密码:
重新输入新的 密码:
passwd:所有的身份验证令牌已经成功更新
[root@hadoop102 ~]# sudo vim /etc/sudoers
vanas ALL=(ALL) ALL
#注意放置位置 以及大小写
[root@hadoop104 ~]# cd /opt/
[root@hadoop104 opt]# mkdir software module
[root@hadoop104 opt]# chown vanas:vanas software/ module/
[root@hadoop104 opt]# ll
总用量 8
drwxr-xr-x 2 vanas vanas 4096 5月 14 15:26 module
drwxr-xr-x 2 vanas vanas 4096 5月 14 15:26 software
编写群发脚本xsync
[vanas@hadoop102 ~]$ mkdir bin
[vanas@hadoop102 ~]$ cd bin
[vanas@hadoop102 bin]$ vim xsync
#!/bin/bash
#1. 判断参数个数
if [ $# -lt 1 ]
then
echo Not Enough Arguement!
exit;
fi
#2. 遍历集群所有机器
for host in hadoop102 hadoop103 hadoop104
do
echo ==================== $host ====================
#3. 遍历所有目录,挨个发送
for file in $@
do
#4 判断文件是否存在
if [ -e $file ]
then
#5. 获取父目录
pdir=$(cd -P $(dirname $file); pwd)
#6. 获取当前文件的名称
fname=$(basename $file)
ssh $host "mkdir -p $pdir"
rsync -av $pdir/$fname $host:$pdir
else
echo $file does not exists!
fi
done
done
[vanas@hadoop102 bin]$ chmod +x xsync
远程访问免密
3台
[vanas@hadoop102 bin]$ ssh-keygen -t rsa
[vanas@hadoop102 bin]$ ssh-copy-id hadoop102
[vanas@hadoop102 bin]$ ssh-copy-id hadoop103
[vanas@hadoop102 bin]$ ssh-copy-id hadoop104
JDK
环境变量设置和分发
[vanas@hadoop102 software]$ tar -zxvf jdk-8u212-linux-x64.tar.gz -C /opt/module/
[vanas@hadoop102 software]$ sudo vim /etc/profile.d/my_env.sh
#JAVA_HOME
export JAVA_HOME=/opt/module/jdk1.8.0_212
export PATH=$PATH:$JAVA_HOME/bin
[vanas@hadoop102 ~]$ java -version
java version "1.8.0_212"
Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)
[vanas@hadoop102 ~]$ xsync /opt/module/jdk1.8.0_212/
[vanas@hadoop102 ~]$ sudo /home/vanas/bin/xsync /etc/profile.d/my_env.sh
source /etc/profile.d/my_env.sh 或重新开始窗口
关于profile.d
/etc/profile.d 登入时加载 ssh Hadoop102 jps 非登入模式
.bachrc
/etc/profile.d/my_env.sh 所以最好用这个方式配
采集日志
mkdir applog
102上传日志文件 并发送给103
[vanas@hadoop103 applog]$ scp hadoop102:/opt/module/applog/gmall2020-mock-log-2020-04-01.jar ./
[vanas@hadoop103 applog]$ scp hadoop102:/opt/module/applog/application.properties ./
[vanas@hadoop103 applog]$ scp hadoop102:/opt/module/applog/path2.json ./
log为后生成的日志
编写脚本(为了方便)
要写绝对路径
[vanas@hadoop102 bin]$ vim log.sh
#!/bin/bash
for i in hadoop102 hadoop103; do
echo "========== $i =========="
ssh $i "cd /opt/module/applog/; java -jar gmall2020-mock-log-2020-04-01.jar >/dev/null 2>&1 &"
done
[vanas@hadoop102 bin]$chmod 777 log.sh
集群所有进程查看脚本
[vanas@hadoop102 bin]$ vim xcall.sh
#! /bin/bash
for i in hadoop102 hadoop103 hadoop104
do
echo --------- $i ----------
ssh $i "$*"
done
[vanas@hadoop102 bin]$ chmod 777 xcall.sh
$* 所有参数看成一个整体
“A1,a2,a3,a4”
@*
“a1” “a2” “a3” “a4”
Hadoop
ssh免密 、jdk已完成
生产环境再配置HA
集群基础配置(重要)
集群规划
服务器hadoop102 | 服务器hadoop103 | 服务器hadoop104 | |
---|---|---|---|
HDFS | NameNodeDataNode | DataNode | DataNodeSecondaryNameNode |
Yarn | NodeManager | ResourcemanagerNodeManager | NodeManager |
解压与安装
[vanas@hadoop102 software]$ tar -zxvf hadoop-3.1.3.tar.gz -C /opt/module/
[vanas@hadoop102 module]$ sudo vim /etc/profile.d/my_env.sh
#在文件末尾 添加(**shift+g**)
##HADOOP_HOME
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin
[vanas@hadoop102 module]$ source /etc/profile.d/my_env.sh
ect/hadoop/ 下有许多配置文件 其中workers 是在hadoop3中 其他版本可能是slaves
[vanas@hadoop102 hadoop]$ vim workers
hadoop102
hadoop103
hadoop104
core-site.xml
3.1多 又改回了8020 3刚开始的时候9820
proxyuser代理用户是hive中beline
a代理b hosts是代理启动 超级用户 可以代理所有用户
group 代理所有组
http hadoop3 可以在web界面 进行目录增删
[vanas@hadoop102 hadoop-3.1.3]$ cd etc/hadoop/
[vanas@hadoop102 hadoop]$ vim core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop102:8020</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/module/hadoop-3.1.3/data</value>
</property>
<property>
<name>hadoop.proxyuser.vanas.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.vanas.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.http.staticuser.user</name>
<value>vanas</value>
</property>
</configuration>
配置项的解读:
dir缓存:
官网说明:
hadoop.tmp.dir /tmp/hadoop-${user.name} A base for other temporary directories.
该地址会被别的配置项所引用如dfs.datanode.data.dir
是一个中间变量 ,间接指定了namenode和datanode的存放位置proxyuser代理说明:
情景:以编写HQL 通过HiveServer2 进而提交给hadoop集群MapReduce为说明:
情况1:
hiveserver2提交任务给到yarn的用户
hiveServer2 :a
beeline用户;a
提交到yarn的用户:a
==============================
情况2:
hiveServer2 :a
beeline用户;b
提交到yarn的用户:a
b的权限低,但提交的权限升高了,可能会造成影响
解决办法:实现代理
hiveServer2 :abeeline用户;b
提交Yarn时 :是a(代理),但是实际执行的Hql是b(代理)
======================================
adoop.proxyuser.atguigu.hosts 和 hadoop.proxyuser.atguigu.groups 指的是
用户可以代理所有用户和所有组
Web用户权限
hadoop.http.staticuser.user 指定Web访问的用户 避免Web用户使用了不同权限用户
补充:对于一个服务来说,谁启动服务,则谁就是这个服务的超级用户,与Linux系统的root无关联
hdfs-site.xml
[vanas@hadoop102 hadoop]$ vim hdfs-site.xml
datenode和namenode都有默认值
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop104:9868</value>
</property>
yarn-site.xml
[vanas@hadoop102 hadoop]$ vim yarn-site.xml
yarn.nodemanager.resource.memory-mb nm交给rm最大资源默认8G
在公司生产环境时服务器一般服务器内存都为128G,需要修改到100G,否则执行缓慢
前两个配置 一个container最多和最少能获得大资源
yarn.scheduler.minimum-allocation-mb
yarn.scheduler.maximum-allocation-mb
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop103</value>
</property>
<property>
<name>yarn.nodemanager.env-whitelist</name> <value>JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME</value>
</property>
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>512</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>4096</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>4096</value>
</property>
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-common/yarn-default.xml
mapred.site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
workers/slaves配置
#配置workers
[vanas@hadoop102 hadoop]$ vim /opt/module/hadoop-3.1.3/etc/hadoop/workers
#在该文件中增加如下内容:
hadoop102
hadoop103
hadoop104
配置历史服务器
配置在哪台在哪台起
[vanas@hadoop102 hadoop]$ vim mapred-site.xml
<!-- 历史服务器端地址 -->
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop102:10020</value>
</property>
<!-- 历史服务器web端地址 -->
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop102:19888</value>
</property>
启动指令
[vanas@hadoop102 hadoop]$ maperd —daemon start historyserver
日志聚集功能
把nodemanager的日志放到hdfs上这样web端就可以查看了
注意:开启日志聚集功能,需要重新启动
[vanas@hadoop102 hadoop]$ vim yarn-site.xml
保留日志时间 7天
历史服务器地址
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://hadoop102:19888/jobhistory/logs</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
启动测试是否可以跑通
#分发
[vanas@hadoop102 module]$ xsync hadoop-3.1.3/
[vanas@hadoop102 module]$ sudo /home/vanas/bin/xsync /etc/profile.d/my_env.sh
[vanas@hadoop102 hadoop-3.1.3]$ hdfs namenode -format
[vanas@hadoop102 ~]$ hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi 1 1
关于集群时间同步
时间同步的方式:找一个机器,作为时间服务器,所有的机器与这台集群时间进行定时的同步,比如,每隔十分钟,同步一次时间。
云服务器不用配
物理机 需要配
关于2nn页面不显示问题
查看dfs-dust.js的第61行
'date_tostring' : function (v) {
return moment(Number(v)).format('ddd MMM DD HH:mm:ss ZZ YYYY');
},
找不到moment函数。在此打断点,并修改函数返回值为:
'date_tostring' : function (v) {
return new Date(Number(v)).toLocaleString();
},
阿里云安全组
9868、8088、19888、9870 web端访问
Hadoop项目经验
HDFS存储多目录
概述:一般生产服务器的磁盘都不止一块,如果要让hdfs的datanode存储在不止一块磁盘,需要配置多目录,同时注意新挂载磁盘的访问权限问题
HDFS的DataNode节点保存数据的路径由dfs.datanode.data.dir参数决定,其默认值为file://${hadoop.tmp.dir}/dfs/data,若服务器有多个磁盘,必须对该参数进行修改。如服务器磁盘如上图所示,则该参数应修改为如下的值
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///dfs/data1,file:///hd2/dfs/data2,file:///hd3/dfs/data3,file:///hd4/dfs/data4</value>
</property>
注意: file:// 充当协议,表示本地文件 /dfs 表示根目录下的dfs
集群数据均衡
节点间的数据均衡
#开启数据均衡命令:
start-balancer.sh –threshold 10
#对于参数10,代表的是集群中各个节点的磁盘空间利用率相差不超过10%,可根据实际情况进行调整。
#停止数据均衡命令:
stop-balancer.sh
磁盘间的数据均衡
(Hadoop3引入的新特性)
针对有多个挂在磁盘
#生成均衡计划
hdfs diskbalancer -plan hadoop102
#执行均衡计划
hdfs diskbalancer -execute hadoop102.plan.json
#查看当前均衡任务的执行情况
hdfs diskbalancer -query hadoop102
#取消均衡任务
hdfs diskbalancer -cancel hadoop102.plan.json
Q:停止时是否对数据有影响
已经完成的 不会变,不会回退
未完成的就不执行Q加了新磁盘后挂载后 , data.dir 多目录 配置时没有配置这个新的磁盘怎么办
必须配置,否则无法使用
LZO配置
因为hadoop自带不具备Lzo压缩类型
优点 可切片
[vanas@hadoop102 software]$ cp hadoop-lzo-0.4.20.jar /opt/module/hadoop-3.1.3/share/hadoop/common/
[vanas@hadoop102 software]$ cd /opt/module/hadoop-3.1.3/share/hadoop/common/
[vanas@hadoop102 common]$ xsync hadoop-lzo-0.4.20.jar
core-site.xml增加配置支持LZO压缩
[vanas@hadoop102 common]$ cd /opt/module/hadoop-3.1.3/etc/hadoop/
[vanas@hadoop102 hadoop]$ vim core-site.xml
<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>
[vanas@hadoop102 hadoop]$ xsync core-site.xml
Hadoop能使用的压缩解压缩格式:
io.compression.codecs
测试lzo
[vanas@hadoop102 hadoop]$ hadoop fs -mkdir /input
[vanas@hadoop102 hadoop]$ hadoop fs -put works /input/
[vanas@hadoop102 hadoop]$ hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount -Dmapreduce.output.fileoutputformat.compress=true -Dmapreduce.output.fileoutputformat.compress.codec=com.hadoop.compression.lzo.LzopCodec /input /output
lzo需要建立索引才可以切片 不建索引依然是一片
建索引
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/common/hadoop-lzo-0.4.20.jar com.hadoop.compression.lzo.DistributedLzoIndexer /input/bigtable.lzo
com.hadoop.compression.lzo.DistributedLzoIndexer 为Lzo官方指定的索引类名
基准测试
集群核心数的确认
开启Hadoop集群后从Yarn上可以观察到集群的核心数量
如果是线上环境,有几核最多就有几个,如图是24个,那么公式为24-1 ,最多可以跑23个maptask 需要预留1个跑appmaster
虚拟机情况下取决于 主机的个数 我的是8核心 既选7个
测试HDFS的读写性能
#写测试,向HDFS集群写10个128M的文件
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -write -nrFiles 10 -fileSize 128MB
#读测试,向HDFS集群读10个128M的文件
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -read -nrFiles 10 -fileSize 128MB
这里以写数据性能分析为例,读性能测试不在缀述
Number of files(集群同时能运行的最多maptask个数): 7
Total MBytes processed(总吞吐量): 896
Throughput mb/sec(): 0.85 单个maptask的吞吐量
计算逻辑:896/(Tm1+Tm2+Tm3+...)
Average IO rate mb/sec: 0.92 单台maptask的吞吐量
计算逻辑:[(m1/Tm1)+(m2/Tm2)+...]/7
IO rate std deviation: 0.21 方差,值越小 maptask之间的差值越小,集群越稳定
Test exec time sec: 308.89 :总用时
MapReduce性能测试
因虚拟机或学习用阿里云无法提供足够的资源,
真实的10台物理机128G内存 的测试参数为 50s
记!!! 不要测试map
Hadoop参数调优
HDFS参数调优hdfs-site.xml
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。
<property>
<name>dfs.namenode.handler.count</name>
<value>10</value>
</property>
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)。
Zookeeper
集群规划:
服务器hadoop102 | 服务器hadoop103 | 服务器hadoop104 | |
---|---|---|---|
Zookeeper | Zookeeper | Zookeeper | Zookeeper |
安装与初始化配置
[vanas@hadoop102 module]$ tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /opt/module/
[vanas@hadoop102 module]$ mv apache-zookeeper-3.5.7-bin/ zookeeper-3.5.7
[vanas@hadoop102 zookeeper-3.5.7]$ mkdir zkData
[vanas@hadoop102 zookeeper-3.5.7]$ cd zkData/
[vanas@hadoop102 zkData]$ vim myid
2
#myid三台分别改
[vanas@hadoop102 zookeeper-3.5.7]$ cd conf/
[vanas@hadoop102 conf]$ mv zoo_sample.cfg zoo.cfg
[vanas@hadoop102 conf]$ vim zoo.cfg
dataDir=/opt/module/zookeeper-3.5.7/zkData
#######################cluster##########################
server.2=hadoop102:2888:3888
server.3=hadoop103:2888:3888
server.4=hadoop104:2888:3888
[vanas@hadoop102 module]$ xsync zookeeper-3.5.7/
**配置参数解读:**server.A=B:C:D
A是一个数字,表示这个是第几号服务器;
集群模式下配置一个文件myid,这个文件在dataDir目录下,这个文件里面有一个数据就是A的值,Zookeeper启动时读取此文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server。
B是这个服务器的地址;
C是这个服务器Follower与集群中的Leader服务器交换信息的端口;
D是万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
群起脚本
[vanas@hadoop102 bin]$ vim zk.sh
#! /bin/bash
case $1 in
"start"){
for i in hadoop102 hadoop103 hadoop104
do
echo ---------- zookeeper $i 启动 ------------
ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh start"
done
};;
"stop"){
for i in hadoop102 hadoop103 hadoop104
do
echo ---------- zookeeper $i 停止 ------------
ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop"
done
};;
"status"){
for i in hadoop102 hadoop103 hadoop104
do
echo ---------- zookeeper $i 状态 ------------
ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh status"
done
};;
esac
[vanas@hadoop102 bin]$ chmod 777 zk.sh
Kafka
集群规划:
服务器hadoop102 | 服务器hadoop103 | 服务器hadoop104 | |
---|---|---|---|
Kafka | Kafka | Kafka | Kafka |
安装与初始化配置
不光是运行日志 还有kafka生产者的topic
/kafka 是放在zookeeper的/kafka路径下
[vanas@hadoop102 software]$ tar -zxvf kafka_2.11-2.4.1.tgz -C /opt/module/
[vanas@hadoop102 module]$ mv kafka_2.11-2.4.1/ kafka
[vanas@hadoop102 kafka_2.11-2.4.1]$ mkdir logs
[vanas@hadoop102 kafka_2.11-2.4.1]$ cd config/
[vanas@hadoop102 config]$ vim server.properties
修改或者增加以下内容:
#broker的全局唯一编号,不能重复 103 104也改
broker.id=0
#删除topic功能使能
delete.topic.enable=true
#kafka运行日志存放的路径
log.dirs=/opt/module/kafka/logs
#配置连接Zookeeper集群地址
zookeeper.connect=hadoop102:2181,hadoop103:2181,hadoop104:2181/kafka
其他默认配置详情(无需要不需改动)
#处理网络请求的线程数量
num.network.threads=3
#用来处理磁盘IO的现成数量
num.io.threads=8
#发送套接字的缓冲区大小
socket.send.buffer.bytes=102400
#接收套接字的缓冲区大小
socket.receive.buffer.bytes=102400
#请求套接字的缓冲区大小
socket.request.max.bytes=104857600
#topic在当前broker上的分区个数
num.partitions=1
#用来恢复和清理data下数据的线程数量
num.recovery.threads.per.data.dir=1
#segment文件保留的最长时间,超时将被删除
log.retention.hours=168
配置环境变量(可以不配)
[vanas@hadoop102 config]$ sudo vi /etc/profile.d/my_env.sh
#KAFKA_HOME
export KAFKA_HOME=/opt/module/kafka
export PATH=$PATH:$KAFKA_HOME/bin
[vanas@hadoop102 config]$ source /etc/profile.d/my_env.sh
群起脚本
[vanas@hadoop102 bin]$ vim kafka.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
[vanas@hadoop102 bin]$ chmod 777 kafka.sh
测试
#创建topic
[vanas@hadoop102 ~]$ kafka-topics.sh --zookeeper hadoop102:2181/kafka --create --topic test --partitions 1 --replication-factor 1
Created topic test.
[vanas@hadoop102 ~]$ kafka-console-producer.sh --broker-list hadoop102:9092 --topic first
[vanas@hadoop103 kafka]$ bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic first
[vanas@hadoop102 kafka]$ kafka-topics.sh --list --bootstrap-server hadoop102:9092
__consumer_offsets
first
test
Kafka项目经验
压力测试
用Kafka官方自带的脚本,对Kafka进行压测。Kafka压测时,可以查看到哪个地方出现了瓶颈(CPU,内存,网络IO)。一般都是网络IO达到瓶颈。
kafka-consumer-perf-test.sh
kafka-producer-perf-test.sh
#生产者
[vanas@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
100000 records sent, 50735.667174 records/sec (4.84 MB/sec), 863.43 ms avg latency, 1184.00 ms max latency, 890 ms 50th, 1160 ms 95th, 1176 ms 99th, 1184 ms 99.9th.
说明:
record-size是一条信息有多大,单位是字节。
num-records是总共发送多少条信息。
throughput 是每秒多少条信息,设成-1,表示不限流,可测出生产者最大吞吐量。
参数解析:本例中一共写入10w条消息,吞吐量为4.84MB/sec,每次写入的平均延迟为863.43毫秒,最大的延迟为1184.00毫秒。
890 ms 50th, 1160 ms 95th, 1176 ms 99th, 1184 ms 99.9th :描绘了延迟的走势图
横轴是所有数据,纵轴为延迟,表征50%的message在863.43s以下,以此类推
#消费者
[vanas@hadoop102 kafka]$ bin/kafka-consumer-perf-test.sh --broker-list hadoop102:9092,hadoop103:9092,hadoop104:9092 --topic test --fetch-size 10000 --messages 10000000 --threads 1
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec, rebalance.time.ms, fetch.time.ms, fetch.MB.sec, fetch.nMsg.sec
WARNING: Exiting before consuming the expected number of messages: timeout (10000 ms) exceeded. You can use the --timeout option to increase the timeout.
2020-05-14 21:19:58:116, 2020-05-14 21:20:09:654, 9.5367, 0.8266, 100000, 8667.0133, 1589462398473, -1589462386935, -0.0000, -0.0001
参数说明:
–zookeeper 指定zookeeper的链接信息
–topic 指定topic的名称
–fetch-size 指定每次fetch的数据的大小
–messages 总共要消费的消息个数
测试结果说明:
start.time, end.time, data.consumed.in.MB, MB/sec, data.consumed.in.nMsg**, nMsg.sec**
2020-05-14 21:19:58:116, 2020-05-14 21:20:09:654, 9.5367, 0.8266, 100000, 8667.0133, 1589462398473, -1589462386935, -0.0000, -0.0001
开始测试时间,测试结束数据,共消费数据9.5368MB,吞吐量0.8266MB/s,共消费100000条,平均每秒消费8667.0133条
机器数量计算
Kafka机器数量(经验公式)=2*(峰值生产速度 * 副本数/100)+1
先拿到峰值生产速度,再根据设定的副本数,就能预估出需要部署Kafka的数量。
比如我们的峰值生产速度是50M/s。副本数为2。
Kafka机器数量=2*(50* *2/100)+ 1=3台
峰值生产速度:M/S
kafka分区数量计算(重点)
1)创建一个只有1个分区的topic
2)测试这个topic的producer吞吐量和consumer吞吐量。
3)假设他们的值分别是Tp和Tc,单位可以是MB/s。
4)然后假设总的目标吞吐量是Tt,那么分区数=Tt / min(Tp,Tc)
例如:producer吞吐量=20m/s;consumer吞吐量=50m/s,期望吞吐量100m/s;
分区数=100 / 20 =5分区
分区数一般设置为:3-10个
Flume
服务器hadoop102 | 服务器hadoop103 | 服务器hadoop104 | |
---|---|---|---|
Flume(采集日志) | 生产 Flume | 生产 Flume | 消费Flume |
安装与初始化配置
[vanas@hadoop102 ~]$ cd /opt/software/
[vanas@hadoop102 software]$ tar -zxf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/
[vanas@hadoop102 software]$ cd ../module/
[vanas@hadoop102 module]$ mv /opt/module/apache-flume-1.9.0-bin /opt/module/flume
[vanas@hadoop102 lib]$ rm guava-11.0.2.jar
[vanas@hadoop102 conf]$ mv flume-env.sh.template flume-env.sh
[vanas@hadoop102 conf]$ vi flume-env.sh
export JAVA_HOME=/opt/module/jdk1.8.0_212
拦截器
上传自定义拦截器jar包 到flum/lib
日志采集flume配置
正则 .*(0-所有) .+(1-所有)
parseAsFlumeEvent 把head去掉
a1.sinks.k1.channel agent 是扇形结构
bootstrap.servers作用 2 个是为了容错
[vanas@hadoop102 flume]$ mkdir jobs
[vanas@hadoop102 jobs]$ vim taildir_kafka.conf
#为各组件命名
a1.sources = r1
a1.channels = c1
#描述source
a1.sources.r1.type = TAILDIR
a1.sources.r1.filegroups = f1
a1.sources.r1.filegroups.f1 = /opt/module/applog/log/app.*
a1.sources.r1.batchSize=500
a1.sources.r1.positionFile = /opt/module/flume/taildir_position.json
a1.sources.r1.interceptors = i1
a1.sources.r1.interceptors.i1.type = com.orange.lin.interceptor.ETLInterceptor$Builder
#描述channel
a1.channels.c1.type = org.apache.flume.channel.kafka.KafkaChannel
a1.channels.c1.kafka.bootstrap.servers = hadoop102:9092,hadoop103:9092
a1.channels.c1.kafka.topic = topic_log
a1.channels.c1.parseAsFlumeEvent = false
#绑定source和channel以及sink和channel的关系
a1.sources.r1.channels = c1
nohup 免挂断
&退到后台
[vanas@hadoop102 flume]$ bin/flume-ng agent -n a1 -c conf/ -f jobs/taildir_kafka.conf -Dflume.root.logger=info,console
[vanas@hadoop103 kafka]$ bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic topic_log
xsync flume
群起脚本
[vanas@hadoop103 kafka]$ nohup /opt/module/flume/bin/flume-ng agent -n a1 -c /opt/module/flume/conf/ -f /opt/module/flume/jobs/taildir_kafka.conf -Dflume.root.logger=info,console >/opt/module/flume/log.txt 2>&1 &
[vanas@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 -n a1 -c /opt/module/flume/conf/ -f /opt/module/flume/jobs/taildir_kafka.conf -Dflume.root.logger=info,console >/opt/module/flume/log.txt 2>&1 &"
done
};;
"stop"){
for i in hadoop102 hadoop103
do
echo " --------停止 $i 采集flume-------"
ssh $i "ps -ef | grep taildir_kafka.conf | grep -v grep |awk '{print \$2}' | xargs -n1 kill -9 "
done
};;
esac
[vanas@hadoop102 bin]$ chmod 777 f1.sh
日志消费Flume配置
[vanas@hadoop104 jobs]$ vim kafka_hdfs.conf
## 组件
a1.sources=r1
a1.channels=c1
a1.sinks=k1
## source1
a1.sources.r1.type = org.apache.flume.source.kafka.KafkaSource
a1.sources.r1.batchSize = 5000
a1.sources.r1.batchDurationMillis = 2000
a1.sources.r1.kafka.bootstrap.servers = hadoop102:9092,hadoop103:9092,hadoop104:9092
a1.sources.r1.kafka.topics=topic_log
## 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
## sink1
a1.sinks.k1.type = hdfs
a1.sinks.k1.hdfs.path = /origin_data/gmall/log/topic_log/%Y-%m-%d
a1.sinks.k1.hdfs.filePrefix = log-
a1.sinks.k1.hdfs.round = false
a1.sinks.k1.hdfs.rollInterval = 10
a1.sinks.k1.hdfs.rollSize = 134217728
a1.sinks.k1.hdfs.rollCount = 0
## 控制输出文件是原生文件。
a1.sinks.k1.hdfs.fileType = CompressedStream
a1.sinks.k1.hdfs.codeC = lzop
## 拼装
a1.sources.r1.channels = c1
a1.sinks.k1.channel= c1
启动脚本
[vanas@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 -n a1 -c /opt/module/flume/conf/ -f /opt/module/flume/jobs/kafka_hdfs.conf -Dflume.root.logger=info,console >/opt/module/flume/log.txt 2>&1 &"
done
};;
"stop"){
for i in hadoop104
do
echo " --------停止 $i 采集flume-------"
ssh $i "ps -ef | grep kafka_hdfs.conf | grep -v grep |awk '{print \$2}' | xargs -n1 kill -9 "
done
};;
esac
[vanas@hadoop102 bin]$ chmod 777 f2.sh
启动时候注意
先把通道打通 再生成数据
f1.sh start
f2.sh start
log.sh
Flume项目经验
Flume组件-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)
Flume组件Channel选型
Kafka Channel
采用Kafka Channel,省去了Sink,提高了效率。KafkaChannel数据存储在Kafka里面,所以数据是存储在磁盘中。
注意在Flume1.7以前,Kafka Channel很少有人使用,因为发现parseAsFlumeEvent这个配置起不了作用。也就是无论parseAsFlumeEvent配置为true还是false,都会转为Flume Event。这样的话,造成的结果是,会始终都把Flume的headers中的信息混合着内容一起写入Kafka的消息中,这显然不是我所需要的,我只是需要把内容写入即可。
FileChannel和MemoryChannel区别
MemoryChannel传输数据速度更快,但因为数据保存在JVM的堆内存中,Agent进程挂掉会导致数据丢失,适用于对数据质量要求不高的需求。
FileChannel传输速度相对于Memory慢,但数据安全保障高,Agent进程挂掉也可以从失败中恢复数据。
选型:
金融类公司、对钱要求非常准确的公司通常会选择FileChannel
传输的是普通日志信息(京东内部一天丢100万-200万条,这是非常正常的),通常选择
MemoryChannel。
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恢复数据
Flume组件Sink选型
Sink:HDFS Sink
(1)HDFS存入大量小文件,有什么影响?
**元数据层面:**每个小文件都有一份元数据,其中包括文件路径,文件名,所有者,所属组,权限,创建时间等,这些信息都保存在Namenode内存中。所以小文件过多,会占用Namenode服务器大量内存,影响Namenode性能和使用寿命
**计算层面:**默认情况下MR会对每个小文件启用一个Map任务计算,非常影响计算性能。同时也影响磁盘寻址时间。
(2)HDFS小文件处理
官方默认的这三个参数配置写入HDFS后会产生小文件,hdfs.rollInterval、hdfs.rollSize、hdfs.rollCount
基于以上hdfs.rollInterval=3600,hdfs.rollSize=134217728,hdfs.rollCount =0几个参数综合作用,效果如下:
(1)文件在达到128M时会滚动生成新文件
(2)文件创建超3600秒时会滚动生成新文件
Flume内存优化
问题描述:如果启动消费Flume抛出如下异常
ERROR hdfs.HDFSEventSink: process failed
java.lang.OutOfMemoryError: GC overhead limit exceeded
解决方案步骤:
(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或更高
-Xmx与-Xms最好设置一致,减少内存抖动带来的性能影响,如果设置不一致容易导致频繁fullgc。
-Xms表示JVM Heap(堆内存)最小尺寸,初始分配;-Xmx 表示JVM Heap(堆内存)最大允许的尺寸,按需分配。如果不设置一致,容易在初始化时,由于内存不够,频繁触发fullgc。fullgc会暂停虚拟机的其他线程,等GC后开启,
其他小问题总结
时间脚本
-t 非root用户 强制生成终端
ntpd 自动同步网上时间 阿里云默认开启
disable 也关掉
kafka时间索引有存储
时间只能往后改不能往前改
zookeeper启动完再启动kafka