在正式介绍 kafka 工作原理之前有必要对依赖的Zookeeper服务做个深入的了解。
Zookeeper 主要用于管理大量主机的协同服务、分布式应用,实现分布式读写技术。
Zookeeper应用场景有:
2 Zookeeper存在的必要
分布式应用程序中,都会有节点的概念,假设有5个可以用来响应用户下单请求的节点。
一个用户请求过来,这个请求应该由哪个节点来操作呢?简单的方式就是5个节点抽签的方式,但是如果某个节点故障了呢?
因此每个节点在抽签需要知道其他节点的状态,那么心跳机制就起作用了,每个节点接收其他节点的心跳并作出响应,相互通知我还活着,如下图所示:
这种方式,看着就很乱,因此需要一个leader, 其他follower全都与leader沟通,相互之间不需要沟通。
但是心跳与应答的消息,如果全都由leader存储处理,那也太累了,而且需要处理大量的同步与异步工作。而且这个工作与业务耦合度非常高,如果遇到其他分布式应用需求,还需要重新设计。
因此将大量同步读写工作,名称空间处理、配置工作、选举工作等都独立出来设计一个服务,如下图所示,专门服务分布式应用程序。Leader只需要下达业务指令,不需要考虑其他同步异步问题。
3 详细搭建过程
上一节中配置了一个kafka容器,kafka中配置了JDK环境,为了简单,直接将kafka容器做成基础镜像,方便zookeeper环境配置。提交容器加入注释。为镜像命名为zookeeper版本号设置为1.0
docker commit kafka -m 'create a zookeeper image' zookeeper:1.0
启动zookeeper镜像,并且命名为zk1容器
docker run -it --name zk1 zookeeper:1.0 bash
通过简单的命令以及可以看出容器已经启动
将zookeeper安装包拷贝到zk1 docker容器中去
docker cp zookeeper-3.4.9.tar.gz zk1:/usr/local/
进入容器中
docker exec -it zk1 bash
解压zookeeper安装包
进入到/usr/local/zookeeper-3.4.9/conf配置文件中
拷贝配置文件
cp zoo_sample.cfg zoo.cfg
把数据路径的位置改一下,防止数据被清除,dada
把路径修改为/usr/local/zookeeper-3.4.9/data
本文准备启动3个zookeeper主机,所以设置了3个server
在dataDir路径里echo 1 >myid 生成一个文件并标上对应的id号
到此一个zookeeper容器就制作成功,提交容器生成zookeeper镜像
此后再需要zookeeper的容器,只需要在对应的镜像上启动一个就行。
docker commit -m 'create and config ' zk1 zookeeper:1.1
默认情况下,docker容器内部都会共用一个bridge网络,这里我创建一个自定义桥接网络backend,供zookeeper集群使用。
docker run -d --network backend -it --name zk3 --hostname zk3 zookeeper:1.1
参数:-d表示后台运行,-it表示能够允许终端进入,如果不设置的话容器会在启动时候自动退出,name是给容器起的别名,hostname是容器主机名
分别启动三个容器,效果如下:
进入到容器内部docker exec -it zk1 bash。目前有3个zookeeper容器分别进入zk2与zk3的dataDir目录中,对应修改myid号,为2、3,分别启动三个zookeeper节点。
这里说明一下,zookeeper不会自动调动其他主机的zookeeper节点,需要手动的去设置各个启动节点。
容器之间相互通信时候,主机名和容器名都会被映射相应的IP,因此使用两者之一就可以通信,不需要知道具体的IP为多少。
启动zookeeper后查看节点状态,得知该节点被选举为leader,那么其他的则为follower
至此zookeeper集群已经搭建完毕。
4
这里提供一个简单一次性启动多个容器的方法,就是docker-compose
创建一个名为docker-compose.yml的文件,在当前目录下 使用docker-compose up就可以一次性启动三个容器。感兴趣的朋友还可以在镜像内添加脚本,容器启动时执行脚本自动配置zookeeper。
version: '2' services: zk1: image: zookeeper:1.2 container_name: zk1 networks: - backend tty: true zk2: image: zookeeper:1.2 container_name: zk2 networks: - backend tty: true zk3: image: zookeeper:1.2 container_name: zk3 networks: - backend tty: true networks: backend: driver: bridge |
---|
5 Zookeeper里面到处存储了什么?
执行连接zookeeper客户端命令,zkCli.sh -server zk1:2181
查看根目录并查看相关信息
我们创建一个节点,并赋值,然后get数据
给一个不存在的路径赋值,会报错,给已经存在的路径节点赋值,dataVersion会更新。
基本上可以下结论,zookeeper里也是以键值对存值,不过键是以一种树形结构形式存在。
zookeeper节点有三种类型:持久节点、临时节点、序列节点
持久节点当client结束的时候依然存在,临时节点只在client活动时候有效,client结束,节点被删除。序列节点可以设置相同名称的节点,会自动在节点名称后面附加10个数字,主要用于同步和锁。
Create [-s][-e] path data acl
Clinet连接zk,可以连接follower也可以连接follower,每次连接成功节点会分配一个ID给client, 然后发送ack信息给client。
如果没有收到返回应答消息,则会选择连接另外一个节点。Client读写数据时候,读数据会从连接的node上读取,写数据则会将请求发送给leader, 然后再有leader发送请求给flollower写数据,当超过一半的节点成功响应leader后,写的操作成功。
本文分享自 程序员郭震zhenguo 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!