使用Kazoo操作ZooKeeper服务治理
单机服务的可靠性及可扩展性有限,某台服务宕机可能会影响整个系统的正常使用;分布式服务能够有效地解决这一问题,但同时分布式服务也会带来一些新的问题,如:服务发现(新增或者删除了服务如何确保能让客户端知道),容灾(某些服务出现故障如何让客户端只访问正常的服务);ZooKeeper的提出主要是为了解决分布式服务的治理问题,它在分布式环境中协调和管理服务。
Zookeeper协调管理服务的过程如下图:
服务端:每台服务器都要向注册中心Zookeeper进行注册登记,并且保持与Zookeeper的连接,如果服务器与Zookeeper断开了连接,Zookeeper将删除该服务器的地址。
客户端:需要服务的时候先向Zookeeper订阅服务器的地址信息,Zookeeper返回给客户端已注册的服务器信息列表,客户端从服务器信息列表中选择服务器进行服务调用,如果Zookeeper记录的服务器信息发生了变更,服务器会通知客户端变更事件,客户端可以获取最新的服务器信息。
ZooKeeper文件系统的数据结构是个树状结构,它的每个节点(znode)由一个名称标识,并用路径/分割:
ZooKeeper的节点类型有:
1. 持久节点(ZooKeeper默认的节点类型,创建该节点的客户端断开连接后,持久节点仍然存在)
2. 顺序节点(将10位的序列号附加到原始名称来设置节点的路径,如:/server0000000001)
3. 临时节点(当客户端与ZooKeeper断开连接时,临时节点会自动删除)
RPC服务注册到ZooKeeper
服务端:
import threading
import json
import socket
import sys
from kazoo.client import KazooClient
from divide_rpc import ServerStub
from divide_rpc import InvalidOperation class ThreadServer(object):
def __init__(self, host, port, handlers):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.host = host
self.port = port
self.sock.bind((host, port))
self.handlers = handlers def serve(self):
"""
开始服务
"""
self.sock.listen(128)
self.register_zk()
print("开始监听")
while True:
conn, addr = self.sock.accept()
print("建立链接%s" % str(addr))
t = threading.Thread(target=self.handle, args=(conn,))
t.start() def handle(self, client):
stub = ServerStub(client, self.handlers)
try:
while True:
stub.process()
except EOFError:
print("客户端关闭连接") client.close() def register_zk(self):
"""
注册到zookeeper
"""
self.zk = KazooClient(hosts='127.0.0.1:2181')
self.zk.start()
self.zk.ensure_path('/rpc') # 创建根节点
value = json.dumps({'host': self.host, 'port': self.port})
# 创建服务子节点
self.zk.create('/rpc/server', value.encode(), ephemeral=True, sequence=True) class Handlers:
@staticmethod
def divide(num1, num2=1):
"""
除法
:param num1:
:param num2:
:return:
"""
if num2 == 0:
raise InvalidOperation()
val = num1 / num2
return val if __name__ == '__main__':
if len(sys.argv) < 3:
print("usage:python server.py [host] [port]")
exit(1)
host = sys.argv[1]
port = sys.argv[2]
server = ThreadServer(host, int(port), Handlers)
server.serve()
服务端通过kazoo连接zookeeper,依次创建根节点和服务的子节点,当启动多线程服务器的时候,会根据ip和端口创建不同的节点,依次启动两个server(8001、8002),查看zookeeper的节点信息:
>>> from kazoo.client import KazooClient
>>> zk = KazooClient(hosts='127.0.0.1:2181')
>>> zk.start()
>>> children = zk.get_children("/rpc")
>>> print(children)
['server0000000001', 'server0000000000']
客户端:
import random
import time
import json
import socket
from divide_rpc import (
ClientStub, InvalidOperation
)
from kazoo.client import KazooClient class DistributedChannel(object):
def __init__(self):
self._zk = KazooClient(hosts='127.0.0.1:2181')
self._zk.start()
self._get_servers() def _get_servers(self, event=None):
"""
从zookeeper获取服务器地址信息列表
"""
servers = self._zk.get_children('/rpc', watch=self._get_servers)
print(servers)
self._servers = []
for server in servers:
data = self._zk.get('/rpc/' + server)[0]
if data:
addr = json.loads(data.decode())
self._servers.append(addr) def _get_server(self):
"""
随机选出一个可用的服务器
"""
return random.choice(self._servers) def get_connection(self):
"""
提供一个可用的tcp连接
"""
while True:
server = self._get_server()
print(server)
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((server['host'], server['port']))
except ConnectionRefusedError:
time.sleep(1)
continue
else:
break
return sock channel = DistributedChannel() for i in range(50):
try:
stub = ClientStub(channel)
val = stub.divide(i)
except InvalidOperation as e:
print(e.message)
else:
print(val)
time.sleep(1)
客户端连接zookeeper,通过get_children来获取服务器信息,并watch监听服务器的变化情况,启动客户端会发现它会调用8001端口的server和8002端口的server:
此时服务端新增加一个结点,8003,客户端变化情况:
可以看出zookeeper总共有三个节点了,前面调用的server都是8001和8002,当8003加入后,zookeeper会发现并调用它
此时服务端断开一个server,8001,客户端变化情况:
断开server前客户端会调用8001、8002、8003这三个服务,当断开server 8001以后,zookeeper只会调用8002和8003这两个server了
使用Kazoo操作ZooKeeper服务治理的更多相关文章
- python使用kazoo操作zookeeper时候出现的"kazoo.exceptions.ConnectionLoss"错误
在往zk中写入数据的时候,突然遇到 “kazoo.exceptions.ConnectionLoss“错误,然而对zk链接进行检查,在set之前状态是”CONNECT“. 经过测试后发现是因为写入的字 ...
- ZooKeeper服务-操作(API、集合更新、观察者、ACL)
操作 create:创建一个znode(必须要有父节点)delete:删除一个znode(该znode不能有任何子节点)exists:测试一个znode是否存在并且查询它的元数据getACL,setA ...
- 个人学习分布式专题(二)分布式服务治理之分布式协调技术Zookeeper
分布式协调技术Zookeeper 2.1 zookeeper集群安装部署(略) 2.2 zookeeper的基本原理,数据模型 2.3 zookeeper Java api的使用 2.4 zookee ...
- 服务治理框架dubbo中zookeeper的使用
Zookeeper提供了一套很好的分布式集群管理的机制,就是它这猴子那个几月层次型的目录树的数据结构,并对书中的节点进行有效的管理,从而可以设计出多种多样的分布式的数据管理模型:下面简要介绍下zook ...
- Dubbo学习笔记1:使用Zookeeper搭建服务治理中心
Zookeeper是Apache Hadoop的子项目,是一个树形的目录服务,支持变更推送,适合作为Dubbo服务的注册中心,工业强度较高,推荐生成环境使用. , 下面结合上图介绍Zookeeper在 ...
- .NET Core微服务之基于Consul实现服务治理
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Consul基础介绍 Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发 ...
- 美团分布式服务通信框架及服务治理系统OCTO
一.什么是OCTO 定义: OCTO是美团的分布式服务通信框架及服务治理系统,属于公司级基础设施,目前尚未开源. 目标: 为公司所有业务提供统一的服务通信框架,使业务具备良好的服务运营能力,轻松实现 ...
- .NET Core微服务之路:基于gRPC服务发现与服务治理的方案
重温最少化集群搭建,我相信很多朋友都已经搭建出来,基于Watch机制也实现了出来,相信也有很多朋友有了自己的实现思路,但是,很多朋友有个疑问,我API和服务分离好了,怎么通过服务中心进行发现呢,这个过 ...
- 【Dalston】【第一章】 服务治理(Eureka)
Spring Cloud是一系列框架的集合,其基于Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,构建了服务治理(发现注册).配置中心.消息总线.负载均衡.断路器.数据监控.分 ...
随机推荐
- python计算素数和
计算输入两个正整数x,y(x<=y,包括x,y)素数和.函数isPrime用以判断一个数是否素数,primeSum函数返回素数和 以下为源码 def isPrime(n) : for i ...
- 分布式协调服务Zookeeper集群搭建
分布式协调服务Zookeeper集群搭建 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.安装jdk环境 1>.操作环境 [root@node101.yinzhengjie ...
- Jmeter 逻辑控制器总结
本文主要总结Jmeter的逻辑控制器: 逻辑控制器下一共16个控制器: 1.foreach controller循环控制器 定义变量数组,按数组遍历循环 2.simple controller 简 ...
- Springboot自定义异常处理
1.自定义异常类 import lombok.Data; @Data public class UserException extends RuntimeException { private Lon ...
- MVC系统过滤器 OutputCacheAttribute
命名空间: System.Web.Mvc程序集: System.Web.Mvc(在 System.Web.Mvc.dll 中) 一.MVC缓存简介 缓存是将信息(数据或页面)放在内存中以避免频繁的 ...
- dsp实验一 常见问题教程
1.选择合适阅读材料:卖油翁.将进酒,等. 2.录音设备三选一:某种电脑声卡+线上convert/楼月mp3录音软件+格式工厂(我选的)/Matlab (注:这是目前已知的方法,我只用了第二个) 3. ...
- idea2017.2.2注册
IntelliJ IDEA 2017.2 破解(注册) 2017年08月10日 11:13:45 筱进GG 阅读数:2849更多 个人分类: IntelliJ IDEA 下载IntelliJ ID ...
- zip4j压缩
使用的jar包:zip4j_1.3.2.jar 基本功能: 针对ZIP压缩文件创建.添加.分卷.更新和移除文件 (读写有密码保护的Zip文件) (支持AES 128/256算法加密) (支持标准Zip ...
- easyui,datagrid表格,行内可编辑
最近用到easyui,需要表格内编辑,但是我同一个页面有多个表格,把官方的代码修改了一下,如下: HTML代码 <table id="dg" class="easy ...
- pointer-events属性屏蔽鼠标事件(点击穿透上层元素)
应用场景 我们在 HTML 开发时可能会遇到这样的情况:页面上有一些元素使用绝对定位布局,这些元素可能会遮盖住它们位置下方的某个元素的部分或者全部.默认情况下,下方元素被遮挡的部分是不会响应鼠标事件的 ...