引言
之前就了解过kafka,看的似懂非懂,最近项目组中引入了kafka,刚好接着这个机会再次学习下。
Kafka在很多公司被用作分布式高性能消息队列,kafka之前我只用过redis的list来做简单的队列处理,也还算好用,可能数据量比较小,也是单机运行,未出现过问题,用作轻量级消息队列还是比较好用的。而redis的作者antirez,设计redis的初衷并不是用来做消息队列,但用它做消息队列的人貌似还挺多,以至于后来antirez后来新开了个项目disque,专门用来做消息队列,但这个不是本文的重点。
在了解kafka的时候,发现他与zookeeper绑定的比较紧密,为了更好的理解kafka,我必须先将zookeeper搞明白。
ZooKeeper是一种分布式协调服务,用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper通过其简单的架构和API解决了这个问题。 ZooKeeper允许开发人员专注于核心应用程序逻辑,而不必担心应用程序的分布式特性。
这是从互联网上引用的一段话,分布式应用不同于单机引用,维护起来非常复杂,现在的分布式系统大部分已经离不开zookeeper(或者类似的解决方案)了,zookeeper简化了分布式应用的管理和部署,本文就通过实例来探讨学习下zookeeper。
实例
本人也是持着学习的态度来写本篇文章的,后文的实例都未在生产环境中使用过,都是学习之后的实践整理,偏向于应用,对其中的算法原理并未深究。有瑕疵遗漏的地方还望斧正。
配置管理
假如,我们线上有个服务器集群,成百上千台服务器,如果更新代码的时候怎么更新呢,一台台机器去更新?就算是强大的麒麟臂爬也要累折了o(╯□╰)o,今天我们就试试用zookeeper来给服务器集群部署代码。
原理
zookeeper提供了节点watch的功能,zookeeper的client(对外提供服务的server)监控zookeeper上的节点(znode),当节点变动的时候,client会收到变动事件和变动后的内容,基于zookeeper的这个特性,我们可以给服务器集群中的所有机器(client)都注册watch事件,监控特定znode,节点中存储部署代码的配置信息,需要更新代码的时候,修改znode中的值,服务器集群中的每一台server都会收到代码更新事件,然后触发调用,更新目标代码。也可以很容易的横向扩展,可以随意的增删机器,机器启动的时候注册监控节点事件即可。
我的机器数量有限,在本地模拟zookeeper集群和服务器集群,原理都是一样的,可能具体实施的时候有些小异。
在本机通过3个端口模拟zookeeper集群,多个目录模拟服务器集群。
zookeeper配置
本文只是模拟,为了方便,所有的节点全在一台机器上,效果是类似的。
创建/path/to/zookeeper/conf/zoo1.cfg
,/path/to/zookeeper/conf/zoo2.cfg
,/path/to/zookeeper/conf/zoo3.cfg
三个文件,配置分别如下:
zoo1.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zk1/data
dataLogDir=/tmp/zk1/log
clientPort=2181
server.1=localhost:2888:3888
server.2=localhost:2899:3899
server.3=localhost:2877:3877
zoo2.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zk2/data
dataLogDir=/tmp/zk2/log
clientPort=2182
server.1=localhost:2888:3888
server.2=localhost:2899:3899
server.3=localhost:2877:3877
zoo3.cfg
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/tmp/zk3/data
dataLogDir=/tmp/zk3/log
clientPort=2183
server.1=localhost:2888:3888
server.2=localhost:2899:3899
server.3=localhost:2877:3877
配置文件中dataDir
,dataLogDir
,clientPort
这三个配置是有差别的。
分别在3个节点对应的dataDir
中建立myid
文件,里面输入服务器标识号
echo 1 > /tmp/zk1/data/myid
echo 2 > /tmp/zk2/data/myid
echo 3 > /tmp/zk3/data/myid
启动三个节点
bin/zkServer.sh start conf/zoo1.cfg
bin/zkServer.sh start conf/zoo2.cfg
bin/zkServer.sh start conf/zoo3.cfg
查看三个节点,可以看到1、3号接节点是follower节点,2号节点是leader节点
? zookeeper bin/zkServer.sh status conf/zoo3.cfg
ZooKeeper JMX enabled by default
Using config: conf/zoo3.cfg
Mode: follower
? zookeeper bin/zkServer.sh status conf/zoo2.cfg
ZooKeeper JMX enabled by default
Using config: conf/zoo2.cfg
Mode: leader
? zookeeper bin/zkServer.sh status conf/zoo1.cfg
ZooKeeper JMX enabled by default
Using config: conf/zoo1.cfg
Mode: follower
客户端代码模拟
from kazoo.client import KazooClient
import time
import json
import subprocess
import os
zk = KazooClient(hosts="10.222.76.148:2181, 10.222.76.148:2182, 10.222.76.148:2183")
zk.start()
FILE_DIR = os.path.split(os.path.realpath(__file__))[0]
'''切换到指定文件夹,不存在的话创建并切换'''
def go_dir(dir_name):
if os.path.exists(dir_name):
pass
else:
os.makedirs(dir_name)
os.chdir(dir_name)
'''从git获取代码'''
def handle_watch(data):
try:
info = json.loads(data)
if