什么是Zookeeper?
Zookeeper是一个分布式服务管理软件,它可以帮助我们完成自动的分布式服务集成以及服务发现
为什么要用Zookeeper?
当我们使用分布式服务时,因此所带来的分布式管理变得尤为重要,所以我们需要这样一个开源软件来协助我们管理所有分布式的服务,提高我们服务的稳定性和可扩展性
安装
Zookeeper是一款托管在Apache基金会的开源软件
下载地址:https://www.apache.org/dyn/closer.cgi/zookeeper/
下载后解压然后需要我们创建一个存放Zookeeper数据的文件夹
在conf/文件夹中我们可以看到一个sample_conf.cfg,可以参照这个配置文件来做自己的配置
启动Zookeeper命令:zkServer start
停止Zookeeper命令:zkServer stop
Zookeeper可以将我们的服务以节点Znode的形式管理,类似于我们的文件管理,每个节点可以保存1MB的内容
持久节点:在客户端创建连接并且创建节点后如果关闭了连接,不会删除Zookeeper中所保存的这个节点的信息,对于别的节点仍旧可见
临时节点:在客户端创建连接并创建节点后,我们如果这个时候断开了客户端的连接,那么之前在连接中所创建的节点以及所保存的数据都将会被清除
顺序节点:在创建节点的时候对于某个服务来说,其他服务是不可见的,所以我们在创建节点的时候就很有可能重名,这个时候我们需要声明这个节点是顺序节点,Zookeeper这个时候就会自动帮我们创建好节点的后缀例如0000000001这样十位数的后缀名
监视:客户端与Zookeeper之间一直会有心跳连接保持,这个时候如果说其中有某一台服务断开了连接,这个时候我们可以通过设置连接的监视来监听这一变化,从而做出一些回调响应
客户端选择kazoo 我们可以使用终端来测试kazoo的基本使用,因为在pycharm中当程序运行完毕后会关闭标准输出,我们就感受不到Zookeeper监视特性给我们带来的效果
from kazoo.client import KazooClient
import json
# 初始化客户端
zk = KazooClient(hosts="127.0.0.1:2181")
# 启动Zookeeper客户端
zk.start()
# 创建节点
zk.ensure_path("/rpc")
addr1 = json.dumps({
"host": "127.0.0.1",
"port": 8001
})
addr2 = json.dumps({
"host": "127.0.0.1",
"port": 8002
})
# 创建节点并在节点保存数据 ephemeral表示是否是临时节点, 是否是顺序节点
zk.create("/rpc/server", addr1.encode(), ephemeral=True, sequence=True)
zk.create("/rpc/server", addr2.encode(), ephemeral=True, sequence=True)
# 获取子节点列表
children = zk.get_children("/rpc")
# 获取某个节点中保存的数据和状态
data, state = zk.get("/rpc/" + children[0])
print("某个节点的data:", data)
def func(event):
print(event)
print(event.__dict__)
print("节点数据发生变化")
print(zk.get_children("/rpc"))
# 监视在获取数据的时候set
n_children = zk.get_children("/rpc", watch=func)
某个节点的data: b'{"host": "127.0.0.1", "port": 8002}'
这个时候已经创建了/rpc 父节点以及两个/rpc/server的子节点
我们在这个时候开启另一个客户端连接并且在/rpc节点下在创建一个节点,这个时候就会触发watch的效果
from kazoo.client import KazooClient
zk = KazooClient(hosts="127.0.0.1:2181")
zk.start()
zk.ensure_path("/rpc")
zk.create("/rpc/server", b"bwisgood", ephemeral=True, sequence=True)
输出: WatchedEvent(type='CHILD', state='CONNECTED', path='/rpc')
{}
节点数据发生变化 ['server0000000004', 'server0000000003', 'server0000000005']
注意这里的watch方法需要在获取子节点数据的时候设置,并且每设置一次就只会生效一次,如果需要固定的回调则需要在代码中获取子节点的时候固定watch参数