Python通过zookeeper实现分布式服务代码解析


Posted in Python onJuly 22, 2020

借助zookeeper可以实现服务器的注册与发现,有需求的时候调用zookeeper来发现可用的服务器,将任务均匀分配到各个服务器上去.

这样可以方便的随任务的繁重程度对服务器进行弹性扩容,客户端和服务端是非耦合的,也可以随时增加客户端.

zk_server.py

import threading
import json
import socket
import sys
from kazoo.client import KazooClient


# TCP服务端绑定端口开启监听,同时将自己注册到zk
class ZKServer(object):
  def __init__(self, host, port):
    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.zk = None

  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, addr))
      t.start()

  # 具体的处理逻辑,只要接收到数据就立即投入工作,下次没有数据本次链接结束
  def handle(self, conn, addr):
    while True:
      data=conn.recv(1024)
      if not data or data.decode('utf-8') == 'exit':
        break
      print(data.decode('utf-8'))
    conn.close()
    print('My work is done!!!')

  # 将自己注册到zk,临时节点,所以连接不能中断
  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)

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 = ZKServer(host, int(port))
  server.serve()

zk_client.py

import random
import sys
import time
import json
import socket

from kazoo.client import KazooClient


# 客户端连接zk,并从zk获取可用的服务器列表
class ZKClient(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连接
    """
    sock = None
    while True:
      server = self._get_server()
      print('server:%s' % 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
if __name__ == '__main__':
  # 模拟多个客户端批量生成任务,推送给服务器执行
  client = ZKClient()
  for i in range(40):
    sock = client.get_connection()
    sock.send(bytes(str(i), encoding='utf8'))
    sock.close()
    time.sleep(1)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
用Python脚本生成Android SALT扰码的方法
Sep 18 Python
Python基础入门之seed()方法的使用
May 15 Python
Python文件去除注释的方法
May 25 Python
Python实现大文件排序的方法
Jul 10 Python
Python与Java间Socket通信实例代码
Mar 06 Python
Python enumerate索引迭代代码解析
Jan 19 Python
Python实现屏幕截图的两种方式
Feb 05 Python
Python切片工具pillow用法示例
Mar 30 Python
对python_discover方法遍历所有执行的用例详解
Feb 13 Python
Python操作SQLite数据库过程解析
Sep 02 Python
Python socket服务常用操作代码实例
Jun 22 Python
Python获取百度热搜的完整代码
Apr 07 Python
Selenium python时间控件输入问题解决方案
Jul 22 #Python
Python基于字典实现switch case函数调用
Jul 22 #Python
Jmeter HTTPS接口测试证书导入过程图解
Jul 22 #Python
使用python批量修改XML文件中图像的depth值
Jul 22 #Python
Python持续监听文件变化代码实例
Jul 22 #Python
Python不支持 i ++ 语法的原因解析
Jul 22 #Python
基于selenium及python实现下拉选项定位select
Jul 22 #Python
You might like
可快速识别放射性物质-国外大神教你diy一个开放式辐射探测器
2020/03/12 无线电
window+nginx+php环境配置 附配置搭配说明
2010/12/29 PHP
PHP扩展程序实现守护进程
2015/04/16 PHP
PHP中preg_match函数正则匹配的字符串长度问题
2015/05/27 PHP
非常实用的php验证码类
2016/05/15 PHP
php使用glob函数遍历文件和目录详解
2016/09/23 PHP
Nigma vs AM BO3 第一场2.13
2021/03/10 DOTA
jquery时间下拉框小例子
2013/04/15 Javascript
利用jq让你的div居中的好方法分享
2013/11/21 Javascript
JavaScript禁止页面操作的示例代码
2013/12/17 Javascript
JavaScript获取按钮所在form表单id的方法
2015/04/02 Javascript
jQuery实现的经典滑动门效果
2015/09/22 Javascript
JS中Eval解析JSON字符串的一个小问题
2016/02/21 Javascript
jquery插件autocomplete用法示例
2016/07/01 Javascript
jQuery插件echarts实现的多柱子柱状图效果示例【附demo源码下载】
2017/03/04 Javascript
基于Vue实现支持按周切换的日历
2020/09/24 Javascript
通过一次报错详细谈谈Point事件
2018/05/17 Javascript
20个最常见的jQuery面试问题及答案
2018/05/23 jQuery
vue动态路由配置及路由传参的方式
2018/05/23 Javascript
JS实现随机抽取三人
2019/11/06 Javascript
JS中的变量作用域(console版)
2020/07/18 Javascript
Javascript前端下载后台传来的文件流代码实例
2020/08/18 Javascript
基于elementUI竖向表格、和并列的案例
2020/10/26 Javascript
JS算法教程之字符串去重与字符串反转
2020/12/15 Javascript
[19:26]TNC vs EG (BO3)
2018/06/07 DOTA
Python MD5加密实例详解
2017/08/02 Python
Python实用技巧之列表、字典、集合中根据条件筛选数据详解
2018/07/11 Python
Python使用QQ邮箱发送邮件报错smtplib.SMTPAuthenticationError
2019/12/20 Python
设置jupyter中DataFrame的显示限制方式
2020/04/12 Python
python asyncio 协程库的使用
2021/01/21 Python
CSS3实现头像旋转效果
2017/03/13 HTML / CSS
三星英国官网:Samsung英国
2018/09/25 全球购物
this关键字的含义
2015/04/08 面试题
欢度春节标语
2014/07/01 职场文书
国庆节慰问信
2015/02/15 职场文书
python实现Thrift服务端的方法
2021/04/20 Python