目录
当我们的数据足够多时,我们需要用到kafka的消息队列进行缓冲,消息队列优势有很多,例如可以削峰填谷,指流量图相对于不使用消息队列流量的流入比较平缓,减少服务器压力;还有应用解耦,当我们一部分产品功能出问题时,其他功能不会有影响;还有异步提速,我们之前发送请求给解耦服务器可能需要200毫秒,但是我们发送给mq(消息队列)可能需要50毫秒,解耦服务器提前将数据存储在消息队列中,这样用户获取数据会更快,提升了用户体验。
Kafka 是一个分布式消息系统,ZooKeeper则是分布式应用程序的协调服务。Kafka 需要借助 ZooKeeper 来完成 Kafka broker 的注册、配置管理、选举(例如 Kafka 具有主从复制能力),以及集群内的各种协调与控制。在 Kafka 中,每个 Broker 在启动时需要向 ZooKeeper 注册自己的 IP 地址、端口、副本信息等元数据信息,并且将其最新的元数据缓存在 Zookeeper。消费者使用 ZooKeeper 来发现和识别可用的 Broker,生产者利用 ZooKeeper 来发现可以接收新消息的 Broker。同时,Kafka 在多数情况下也依赖于 ZooKeeper 来处理请求路由、Topic 状态监测等功能。可以说,ZooKeeper 是 Kafka 集群中必不可少的组成部分,两者相辅相成,共同形成具有高度弹性和容错性的系统架构,我们先来介绍zookeeper。
部署zookeeper单点
1、下载zookeeper,因为之前在zookeeper部署了免密钥,所以我们在ELK103先单点部署,再用脚本同步到其他节点实现集群部署
[root@ELK103 ~]# wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.1/apache-zookeeper-3.8.1-bin.tar.gz --no-check-certificate
2、解压软件包
[root@ELK103 ~]# tar xf apache-zookeeper-3.8.1-bin.tar.gz -C /koten/softwares/
3、配置环境变量,方便调用
[root@ELK103 ~]# cat /etc/profile.d/zk.sh
#!/bin/bash
export ZK_HOME=/koten/softwares/apache-zookeeper-3.8.1-bin
export PATH=$PATH:$ZK_HOME/bin
[root@ELK103 ~]# source /etc/profile.d/zk.sh
4、创建配置文件
[root@ELK103 ~]# cp /koten/softwares/apache-zookeeper-3.8.1-bin/conf/{zoo_sample,zoo}.cfg
5、启动zookeeper服务
此时如果有jdk的话就会启动,没有的话会提示找不到JAVA_HOME,在上面环境变量里面配置下即可。
[root@ELK103 ~]# zkServer.sh start #启动zookeeper
ZooKeeper JMX enabled by default
Using config: /koten/softwares/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@ELK103 ~]# zkServer.sh status #查看zookeeper
ZooKeeper JMX enabled by default
Using config: /koten/softwares/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: standalone
[root@ELK103 ~]# zkServer.sh stop #停止zookeeper
ZooKeeper JMX enabled by default
Using config: /koten/softwares/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Stopping zookeeper ... STOPPED
[root@ELK103 ~]# zkServer.sh restart #重启zookeeper
ZooKeeper JMX enabled by default
Using config: /koten/softwares/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
ZooKeeper JMX enabled by default
Using config: /koten/softwares/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Stopping zookeeper ... no zookeeper to stop (could not find file /tmp/zookeeper/zookeeper_server.pid)
ZooKeeper JMX enabled by default
Using config: /koten/softwares/apache-zookeeper-3.8.1-bin/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
6、确定zookeeper服务后,测试zookeeper服务是否可用
[root@ELK103 ~]# zkCli.sh
......
[zk: localhost:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: localhost:2181(CONNECTED) 1]
部署zookeeper集群
1、创建配置文件
[root@ELK103 ~]# cat > /koten/softwares/apache-zookeeper-3.8.1-bin/conf/zoo.cfg <<EOF
# 定义最小单元的时间范围tick。
tickTime=2000
# 启动时最长等待tick数量。
initLimit=5
# 数据同步时最长等待的tick时间进行响应ACK
syncLimit=2
# 指定数据目录
dataDir=/koten/data/zk
# 监听端口
clientPort=2181
# 开启四字命令允许所有的节点访问。
4lw.commands.whitelist=*
# server.ID=A:B:C[:D]
# ID:
# zk的唯一编号。
# A:
# zk的主机地址。
# B:
# leader的选举端口,是谁leader角色,就会监听该端口。
# C:
# 数据通信端口。
# D:
# 可选配置,指定角色。
server.101=10.0.0.101:2888:3888
server.102=10.0.0.102:2888:3888
server.103=10.0.0.103:2888:3888
EOF
2、同步zookeeper软件包及目录结构
[root@ELK103 ~]# mkdir /koten/data/zk
[root@ELK103 ~]# data_rsync.sh /koten/softwares/apache-zookeeper-3.8.1-bin/
===== rsyncing elk101: apache-zookeeper-3.8.1-bin =====
命令执行成功!
===== rsyncing elk102: apache-zookeeper-3.8.1-bin =====
命令执行成功!
[root@ELK103 ~]# data_rsync.sh /koten/data/zk
===== rsyncing elk101: zk =====
命令执行成功!
===== rsyncing elk102: zk =====
命令执行成功!
[root@ELK103 ~]# data_rsync.sh /etc/profile.d/zk.sh
===== rsyncing elk101: zk.sh =====
命令执行成功!
===== rsyncing elk102: zk.sh =====
命令执行成功!
[root@ELK103 ~]# for ((host_id=101;host_id<=103;host_id++)) do ssh elk${host_id} "source /etc/profile.d/zk.sh";done #执行环境变量的脚本,后面管理脚本中仍需要source
3、每个zookeeper节点创建唯一标识ID
[root@ELK103 ~]# for ((host_id=101;host_id<=103;host_id++)) do ssh elk${host_id} "echo ${host_id} > /koten/data/zk/myid";done
4、编写zookeeper集群管理脚本
[root@ELK103 ~]# cat /usr/local/sbin/manager_zk.sh
#!/bin/bash
#判断用户是否传参
if [ $# -ne 1 ];then
echo "无效参数,用法为: $0 {start|stop|restart|status}"
exit
fi
#获取用户输入的命令
cmd=$1
#定义函数功能
function zookeeperManger(){
case $cmd in
start)
echo "启动服务"
remoteExecution start
;;
stop)
echo "停止服务"
remoteExecution stop
;;
restart)
echo "重启服务"
remoteExecution restart
;;
status)
echo "查看状态"
remoteExecution status
;;
*)
echo "无效参数,用法为: $0 {start|stop|restart|status}"
;;
esac
}
#定义执行的命令
function remoteExecution(){
for (( i=101 ; i<=103 ; i++ )) ; do
tput setaf 2
echo ========== elk${i} zkServer.sh $1 ================
tput setaf 9
ssh elk${i} "source /etc/profile.d/zk.sh; zkServer.sh $1 2>/dev/null" #这里注意需要先source,我理解的是因为ssh会进入不同的shell环境
done
}
#调用函数
zookeeperManger
[root@ELK103 ~]# chmod +x /usr/local/sbin/manager_zk.sh
5、启动zookeeper集群
[root@ELK103 ~]# manager_zk.sh start
启动服务
========== elk101 zkServer.sh start ================
Starting zookeeper ... STARTED
========== elk102 zkServer.sh start ================
Starting zookeeper ... STARTED
========== elk103 zkServer.sh start ================
Starting zookeeper ... STARTED
6、查看集群状态
注意查看Mode是否有standalone,有的话检查脚本是否有问题,用脚本都停掉后检查那个主机是否还占用端口没有真正停掉
[root@ELK103 ~]# manager_zk.sh status
查看状态
========== elk101 zkServer.sh status ================
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
========== elk102 zkServer.sh status ================
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: leader
========== elk103 zkServer.sh status ================
Client port found: 2181. Client address: localhost. Client SSL: false.
Mode: follower
[root@ELK103 ~]# ss -ntl|grep 2181
LISTEN 0 50 [::]:2181 [::]:*
zookeeper的leader选举流程
一、前情提要
上面我们可以看到,我们的集群启动脚本的时候,elk102成为了leader,这其实并不是随机的,是有一定的原理的,我们需要先了解两个概念,一个是myid,表示当前zookeeper server的server id,用于当前服务器的唯一标识,另一个是zxid,表示zookeeper transaction id,即zookeeper集群事务id,我们一开始集群部署,事务id肯定都为0,那么我们选举都是根据myid来选
二、选举流程
1、脚本是串行启动,启动elk101和elk102这两个节点,先检查有没有Leader 节点,如果 Leader 已经存在,那么这些节点会进入 following 状态。没有的话,两个节点进入looking状态
2、若没有leader角色,elk101和elk102这两个节点会投自己一票,此时elk101节点启动zk服务,开始发起投票,此时myid为101,zxid为0,elk102节点启动zk服务,开始发起投票,此时myid为102,zxid为0
3、两个节点接收彼此的投票信息,进行对比;首先会检查zxid,即事务id,谁的zxid较大谁会优先称为leader;如果zxid相同,则会比较myid,较大的myid作为leader服务器。一旦确定leader角色,此时leader服务器状态变更为leading,没有leader角色的节点主懂变为following
4、elk节点启动,检查有没有leader,发现集群leader在上一步已经存在,所以主动变更为following状态,elk103也变成follower
5、集群半数以上的节点投票完毕就已经确定了leader角色,无需全票通过
zookeeper基于zab协议写入数据原理
一、前期提要
zookeeper的leader与follower有点类似于ES的主分片与副本分片,都有半数以上投票机制,leader接收到写的请求,follower会跟着一起写,半数以上写入成功就算写入成功,leader有读写权限,follower是只读权限
zookeeper原子广播原理,即Zookeeper Atomic Broadcast(简称ZAB)
zookeeper是通过zab协议来保证分布式事务的最终一致性
二、写入流程
1、客户端对follower节点发起写操作
2、follower节点将请求转发给leader
3、leader生成一个新的事务并为这个事务生成一个分布式唯一ZXID,leader将这个事务提议(propose)发送给所有的followers节点
4、所有的follower角色开始写入数据,并将响应的结果返回给leader,即响应ACK
5、leader节点收到ACK后,需要当前集群半数以上的ACK写入成功,即提交本次事务
6、数据写入成功则响应客户端
zookeeper客户常用命令
一、连接客户端
zkCli.sh 连接本地
zkCli.sh -server elk101:2181 连接指定节点
zkCli.sh -server elk101:2181,elk102:2181,elk103:2181 连接集群
二、zookeeper的基本使用
掌握增删改查即可
增
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 0] create /linux
Created /linux #在/下创建linux的znode,类似于linux系统的目录
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 1] create /school koten
Created /school #创建/school的同时写入koten的数据
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 2] create /school/class linux
Created /school/class #在/shool下创建一个名为class的znode,znode为永久节点
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 3] create -s /school/class 123
Created /school/class0000000001 #创建/school/class,由于节点存在,所以自动在后面生成数值,-s表示创建的节点序列化且唯一
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 13] create -e /linshi 123
Created /linshi #-e参数表示创建临时节点
查
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 5] ls / #查看/路径下有多少个znode
[linux, school, zookeeper]
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 6] get /linux #查看/linux是否有数据
null
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 7] get /school
koten
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 8] stat /school #查看/school的znode状态信息
cZxid = 0x800000005
ctime = Sun Jun 04 10:30:03 CST 2023
mZxid = 0x800000005
mtime = Sun Jun 04 10:30:03 CST 2023
pZxid = 0x800000007
cversion = 2
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0 #0x0表示znode为永久节点
dataLength = 5
numChildren = 2
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 15] stat /linshi
cZxid = 0x800000009
ctime = Sun Jun 04 10:46:04 CST 2023
mZxid = 0x800000009
mtime = Sun Jun 04 10:46:04 CST 2023
pZxid = 0x800000009
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x6500067fbda70001 #0x...表示znode为临时节点
dataLength = 3
numChildren = 0
改
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 11] set /linux 123 #修改/linux的znode数据
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 12] get /linux
123
删
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 16] delete /linux #删除/linux的znode
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 17] deleteall /school #递归删除/school下所有的znode数据
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 18] ls /
[linshi, zookeeper]
使用zkWeb.jar来管理ZK集群
1、下载zkWeb.jar(链接放在文末)
2、运行jar包
[root@ELK101 ~]# nohup java -jar zkWeb-v1.2.1.jar &>/tmp/zkWeb.log &
.jar ---> java -jar 直接启动
.war ---> 借助tomcat工具进行解压后使用。
3、浏览器访问10.0.0.101:8099,zkWeb软件默认端口是8099
点击上面节点,可以看到我们的节点树,中间显示可以添加内容保存,右边显示状态
添加节点,保存数据为123
可以看到与命令行中的一致
[root@ELK103 ~]# zkCli.sh -server elk101:2181,elk102:2181,elk103:2181
......
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 0] ls /
[linux666, zookeeper]
[zk: elk101:2181,elk102:2181,elk103:2181(CONNECTED) 1] get /linux666
123
KAFKA单点部署
1、下载kafka软件包
官网下载链接:
https://kafka.apache.org/downloads
[root@ELK101 ~]# wget https://archive.apache.org/dist/kafka/3.2.1/kafka_2.13-3.2.1.tgz
2、解压软件包
[root@ELK101 ~]# tar xf kafka_2.13-3.2.1.tgz -C /koten/softwares/
3、配置环境变量
[root@ELK101 ~]# cat /etc/profile.d/kafka.sh
#!/bin/bash
export KAFKA_HOME=/koten/softwares/kafka_2.13-3.2.1
export PATH=$PATH:${KAFKA_HOME}/bin
[root@ELK101 ~]# source /etc/profile.d/kafka.sh
4、修改配置文件
[root@ELK101 ~]# egrep -v '^$|^*#' /koten/softwares/kafka_2.13-3.2.1/config/server.properties
broker.id=101
......
log.dirs=/koten/data/kafka
......
#集群信息+chroot信息
zookeeper.connect=elk101:2181,elk102:2181,elk103:2181/kafka-3.2.1
......
#注意:此处的chroot在kafka启动后会自动创建zookeeper的节点,这样操作方便在一个zookeeper里部署多个kafka集群,便于管理。
5、启动kafka服务
[root@ELK101 ~]# kafka-server-start.sh /koten/softwares/kafka_2.13-3.2.1/config/server.properties
此处启动需要注意,这个脚本下的JAVA_HOME是否正确
cat /koten/softwares/kafka_2.13-3.2.1/bin/kafka-run-class.sh
...
# Which java to use
if [ -z "$JAVA_HOME" ]; then
JAVA="java"
else
JAVA="$JAVA_HOME/java"
fi
KAFKA集群部署
脚本同步方法见该文章:【运维知识大神篇】超详细的ELFK日志分析教程8(filebeat多行匹配+filestream替换log类型+ES集群修复脚本+ES集群加密+角色访问控制+ES集群配置HTTPS加密)
1、用之前的脚本同步kafka程序包到其他节点
[root@ELK101 ~]# data_rsync.sh /koten/softwares/kafka_2.13-3.2.1/
[root@ELK101 ~]# data_rsync.sh /etc/profile.d/kafka.sh
2、修改其他节点的配置文件,主要是修改host_id
[root@ELK101 ~]# for ((host_id=101;host_id<=103;host_id++)) do ssh elk${host_id} "sed -ri 's#(broker.id=)101#\1${host_id}#g' $KAFKA_HOME/config/server.properties";done
3、各节点启动服务
[root@ELK101 ~]# for ((host_id=101;host_id<=103;host_id++)) do ssh elk${host_id} "kafka-server-start.sh -daemon $KAFKA_HOME/config/server.properties ";done
扩展
一、zabbix监控zookeeper、kafka集群
使用zabbix监控zookeeper和kafka集群有现成的模板,比较方便。
1、在三台主机上部署zabbix客户端
rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm
yum clean all
yum -y install zabbix-agent-5.0.34
sed -r -i 's#^Server=127.0.0.1#Server=10.0.0.71#g' /etc/zabbix/zabbix_agentd.conf|grep Server
systemctl enable --now zabbix-agent.service
2、依次添加三台主机
3、在最新数据可以查到zookeeper的数据
4、kafka需要通过JMX的模板去监控,所以需要配置下java-gateway
[root@Zabbix ~]# yum -y install zabbix-java-gateway
[root@Zabbix ~]# systemctl enable --now zabbix-java-gateway.service
[root@Zabbix ~]# cat /etc/zabbix/zabbix_server.conf
...
JavaGateway=127.0.0.1
...
JavaGatewayPort=10052
...
StartJavaPollers=3
[root@Zabbix ~]# systemctl restart zabbix-server.service
# 三个节点都添加
[root@ELK101 ~]# cat /koten/softwares/kafka_2.13-3.2.1/bin/kafka-server-start.sh
...
if [ "x$KAFKA_HEAP_OPTS" = "x" ]; then
export KAFKA_HEAP_OPTS="-Xmx1G -Xms1G"
export JMX_PORT="9999" # 添加此行
fi
...
# 三个节点都启动服务
[root@ELK101 ~]# nohup kafka-server-start.sh /koten/softwares/kafka_2.13-3.2.1/config/server.properties &
5、在zabbix页面修改主机信息
增加端口
增加链接的模板
三台主机都需要操作
6、查看最新数据,可以监控到kafka的信息了。
二、Loki+Grafana
常见的日志处理方案有ELK、EFK、ELFK、ELFK+KAFKA、Loki+grafana
Loki和Grafana是是除了类似于ELFK的日志分析系统。Loki是一个可扩展、分布式的日志聚合系统,它能够接收、索引和存储日志数据,并且可视化这些数据。Grafana则是一个流行的开源数据可视化工具,支持从各种不同的数据源中提取数据并将其以各种方式可视化。
Loki可以通过promtail采集器从各种不同的日志来源(如文件、系统日志)中采集数据,并将这些日志数据发送到Loki服务器进行处理和存储。然后,Grafana可以连接到Loki服务器并使用Loki作为其数据源来创建各种仪表板和可视化。
使用Loki和Grafana可以有效地监控应用程序产生的日志,并快速了解应用程序运行状况。而且相对于ELFK来说,Loki+grafana比较轻量,等有机会单独出一篇文章!
zookeeper图形化管理工具下载链接:https://pan.baidu.com/s/1ouRFP5TYd8C4xhtTmH-Zdw?pwd=rcdn
我是koten,10年运维经验,持续分享运维干货,感谢大家的阅读和关注!