Kazoo Python Zookeeper 选主
时间:2022-05-03
本文章向大家介绍Kazoo Python Zookeeper 选主,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
本文讲述基于zookeeper选主与故障切换的方法。我们的例子使用的是python。
使用的库是kazoo,安装方式
pip install kazoo
应用场景:
- 多个实例部署,但不是“去中心化”的部署方式;
- 有且只有一个节点作为master,履行master的职责,在例子中是注册调度器;
- 其他实例作为slave,不提供调度功能,但是在master节点挂掉之后,可以重新进行选主调度。
1、注册调度器
我们只给出伪代码,简单的打印调度器注册结果。
# -*- coding:utf-8 -*-
# 调度器注册和关闭
# 模拟主节点的职责
class MyScheduler(object):
# 注册调度器
def init_scheduler(self):
print '########## 开启调度器成功 ############'
# 关闭调度器
def stop_scheduler(self):
print '########## 关闭调度器成功 ############'
2、选主与故障切换代码
1)使用add_listener注册监听器,监听zookeeper会话超时,Session Expired,否则在会话超时的场景中会出现锁不一致的问题,可以参看这篇文章。
- 会话超时之后,我们要重新建立Session,在我们的例子里,会循环直到Session重新建立。
- 重新注册Watcher,因为Watcher会随着Session失效而失效。在我们的例子里,通过执行get_children重新注册了Watcher。
2)向zookeeper注册自己,使用参数makepath=True级联创建节点;使用参数ephemeral=True, sequence=True参数,也就是创建临时有序节点:
- 当实例挂掉,session断开,注册的节点会自行消失
- 有序节点,会节点后添加一个有序编号
3)注册Watcher,观察/dmonitor/master的子节点,当发生以下事件时:
- Created:新增子节点
- Deleted:删除子节点
- Changed:子节点数据变化
- Child:子节点的下一级节点
进行重新选主。
# -*- coding:utf-8 -*-
import socket
import traceback
from kazoo.client import KazooClient
from kazoo.client import KazooState
from MyScheduler import MyScheduler
class HAMaster(object):
def __init__(self):
self.path = '/dmonitor/master'
self.scheduler = MyScheduler()
self.zk = KazooClient('10.93.21.21:2181,10.93.18.34:2181,10.93.18.35:2181', timeout=10)
self.zk.start()
self.zk.add_listener(self.my_listener)
self.is_leader = False
def create_instance(self):
instance = self.path + '/' + socket.gethostbyname(socket.gethostname()) + '-'
self.zk.create(path=instance, value="", ephemeral=True, sequence=True, makepath=True)
# 选主逻辑: master节点下, 所有ephemeral+sequence类型的节点中, 编号最大的获得领导权.
def choose_master(self):
print "########## 选主开始 ############"
instance_list = self.zk.get_children(path=self.path, watch=self.my_watcher)
instance = max(instance_list).split('-')[0]
# 本实例获得领导权
if instance == socket.gethostbyname(socket.gethostname()):
if not self.is_leader:
self.scheduler.init_scheduler()
self.is_leader = True
print "######### 我被选为master, 我以前不是master, 注册调度 ##########"
else:
print "######### 我被选为master, 我以前是master, 不再注册调度 ##########"
# 本实例没有获得领导权
else:
if self.is_leader:
self.scheduler.stop_scheduler()
self.is_leader = False
print "######### 我被选为slave, 我以前不是slave, 关闭调度 ##########"
else:
print "######### 我被选为slave, 我以前是slave, 不再关闭调度 ##########"
print "########## 选主完成 ############"
def my_listener(self, state):
if state == KazooState.LOST:
print "########## 会话超时:KazooState.LOST ############"
while True:
try:
self.create_instance()
self.zk.get_children(path=self.path, watch=self.my_watcher)
print "########## 会话超时:重建会话完成! ############"
break
except Exception, _:
traceback.print_exc()
elif state == KazooState.SUSPENDED:
print "########## 会话超时:KazooState.SUSPENDED ############"
elif state == KazooState.CONNECTED:
print "########## 会话超时:KazooState.CONNECTED ############"
else:
print "########## 会话超时:非法状态 ############"
def my_watcher(self, event):
if event.state == "CONNECTED" and event.type == "CREATED" or event.type == "DELETED" or event.type == "CHANGED" or event.type == "CHILD":
print "########## 监听到子节点变化事件 ############"
self.choose_master()
else:
print "########## 监听到未识别的事件 ############"
3、测试一下
测试代码如下
# -*- coding:utf-8 -*-
import time
from HAMaster import HAMaster
ha = HAMaster()
# 向zk注册自己
ha.create_instance()
# 进行选主
ha.choose_master()
while 1:
time.sleep(10)
运行这个脚本,模拟如下几个场景:
1)初始选主
顺序在两台机器上启动测试脚本。
client10
[data_monitor@bigdata-arch-client10 zookeeper]$ python run.py
client11
[data_monitor@bigdata-arch-client11 zookeeper]$ python run.py
client10输出
[data_monitor@bigdata-arch-client10 zookeeper]$ python run.py
########## 选主开始 ############
########## 开启调度器成功 ############
######### 我被选为master, 我以前不是master, 注册调度 ##########
########## 选主完成 ############
########## 监听到子节点变化事件 ############
########## 选主开始 ############
######### 我被选为master, 我以前是master, 不再注册调度 ##########
########## 选主完成 ############
client11输出
[data_monitor@bigdata-arch-client11 zookeeper]$ python run.py
########## 选主开始 ############
######### 我被选为slave, 我以前是slave, 不再关闭调度 ##########
########## 选主完成 ############
可以看到,client10倍选为主节点并注册调度器,client11作为slave节点。
2)主实例挂掉
我们把client10上的实例kill掉。
client10上不再输出
client11上总体输出如下
[data_monitor@bigdata-arch-client11 zookeeper]$ python run.py
########## 选主开始 ############
######### 我被选为slave, 我以前是slave, 不再关闭调度 ##########
########## 选主完成 ############
########## 监听到子节点变化事件 ############
########## 选主开始 ############
########## 开启调度器成功 ############
######### 我被选为master, 我以前不是master, 注册调度 ##########
########## 选主完成 ############
可以看到监听到节点的变化,并进行了重新选主,client11被选为主节点(只剩他了)并注册了调度器。
tips:观察到节点变化的实效性是通过timeout=10参数控制的,也就是超过10s session不能维持就会认为实例挂了,zookeeper会删除节点。
- 快速入门系列--CLR--01基本概念
- 区块链技术的DOS阶段——智能合约上
- mmc如何管理本机上的(数字/x.509)证书
- Jquery $.extend的重载方法详述
- Jquery ajax调用后台aspx后台文件方法(不是ashx)
- [原创]x.509证书在WCF中的应用(CS篇)
- tomcat
- 快速入门系列--WebAPI--01基础
- 分析程序员到底是不是吃青春饭
- Jquery dom搜索之siblings()方法
- 汽车黑科技!想想以后不是我们亲自驾驶汽车还是蛮开心的
- 快速入门系列--CLR--02多线程
- JavaScript之将JS代码放在什么位置最合适
- 快速入门系列--TSQL-01基础概念
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- php session_decode函数用法讲解
- 解决python对齐错误的方法
- 详解pyinstaller生成exe的闪退问题解决方案
- PHP递归算法的简单实例
- Yii2框架操作数据库的方法分析【以mysql为例】
- 使用OpenCV实现道路车辆计数的使用方法
- python中tab键是什么意思
- PHP实时统计中文字数和区别
- PHP单例模式实例分析【防继承,防克隆操作】
- Python基于network模块制作电影人物关系图
- tp5(thinkPHP5框架)使用DB实现批量删除功能示例
- 统计PHP目录中的文件数方法
- python json.dumps() json.dump()的区别详解
- Win10下用Anaconda安装TensorFlow(图文教程)
- TP5(thinkPHP框架)实现后台清除缓存功能示例