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模块学习 filecmp 文件比较
Aug 27 Python
python通过urllib2爬网页上种子下载示例
Feb 24 Python
python网络编程实例简析
Sep 26 Python
python通过urllib2获取带有中文参数url内容的方法
Mar 13 Python
wxpython实现图书管理系统
Mar 12 Python
PyQt5实现五子棋游戏(人机对弈)
Mar 24 Python
Ubuntu18.04下python版本完美切换的解决方法
Jun 14 Python
实例详解Python模块decimal
Jun 26 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
Nov 15 Python
利用setuptools打包python程序的方法步骤
Jan 18 Python
django models里数据表插入数据id自增操作
Jul 15 Python
python+pytest接口自动化之token关联登录的实现
Apr 06 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
随机头像PHP版
2006/10/09 PHP
PHP读取XML值的代码(推荐)
2011/01/01 PHP
ThinkPHP3.0略缩图不能保存到子目录的解决方法
2012/09/30 PHP
PHP实现将视频转成MP4并获取视频预览图的方法
2015/03/12 PHP
php使用glob函数遍历文件和目录详解
2016/09/23 PHP
PHP7匿名类用法分析
2016/09/26 PHP
php中文乱码问题的终极解决方案汇总
2017/08/01 PHP
基于Jquery的开发个代阴影的对话框效果代码
2011/07/28 Javascript
jQuery EasyUI API 中文文档 - Draggable 可拖拽
2011/09/29 Javascript
JavaScript实现自己的DOM选择器原理及代码
2013/03/04 Javascript
js判断运行jsp页面的浏览器类型以及版本示例
2013/10/30 Javascript
利用jq让你的div居中的好方法分享
2013/11/21 Javascript
jquery.post用法之type设置问题
2014/02/24 Javascript
js二维数组定义和初始化的三种方法总结
2014/03/03 Javascript
jquerymobile局部渲染的各种刷新方法小结
2014/03/05 Javascript
JQuery的ON()方法支持的所有事件罗列
2015/02/28 Javascript
浅谈js中的闭包
2015/03/16 Javascript
php常见的页面跳转方法汇总
2015/04/15 Javascript
纯JavaScript基于notie.js插件实现消息提示特效
2016/01/18 Javascript
JavaScript 获取元素在父节点中的下标(推荐)
2017/06/28 Javascript
详解JavaScript对数组操作(添加/删除/截取/排序/倒序)
2019/04/28 Javascript
layui中select,radio设置不生效的解决方法
2019/09/05 Javascript
JS实现吸顶特效
2020/01/08 Javascript
Python实现pdf文档转txt的方法示例
2018/01/19 Python
python实现朴素贝叶斯分类器
2018/03/28 Python
Python实现重建二叉树的三种方法详解
2018/06/23 Python
python实现根据文件关键字进行切分为多个文件的示例
2018/12/10 Python
django-allauth入门学习和使用详解
2019/07/03 Python
用Python进行websocket接口测试
2020/10/16 Python
Python绘制数码晶体管日期
2021/02/19 Python
丝芙兰法国官网:SEPHORA法国
2016/09/01 全球购物
英语一分钟演讲稿
2014/04/29 职场文书
任命书怎么写
2014/06/04 职场文书
MySQL 那些常见的错误设计规范,你都知道吗
2021/07/16 MySQL
golang定时器
2022/04/14 Golang
APP界面设计技巧和注意事项
2022/04/29 杂记