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操作时间和日期之asctime()方法的使用
May 22 Python
基于Linux系统中python matplotlib画图的中文显示问题的解决方法
Jun 15 Python
详解从Django Rest Framework响应中删除空字段
Jan 11 Python
Python数据可视化教程之Matplotlib实现各种图表实例
Jan 13 Python
python定时按日期备份MySQL数据并压缩
Apr 19 Python
python中数组和矩阵乘法及使用总结(推荐)
May 18 Python
Python线上环境使用日志的及配置文件
Jul 28 Python
Python 读取用户指令和格式化打印实现解析
Sep 02 Python
python 多进程和协程配合使用写入数据
Oct 30 Python
python 通过exifread读取照片信息
Dec 24 Python
基于注解实现 SpringBoot 接口防刷的方法
Mar 02 Python
pytorch锁死在dataloader(训练时卡死)
May 28 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 获取MSN好友列表的代码(2009-05-14测试通过)
2009/09/09 PHP
PHP伪静态Rewrite设置之APACHE篇
2014/07/30 PHP
PHP常见过waf webshell以及最简单的检测方法
2019/05/21 PHP
yii2.0框架使用 beforeAction 防非法登陆的方法分析
2019/09/11 PHP
jquery $(document).ready() 与window.onload的区别
2009/12/28 Javascript
JavaScript 异步方法队列链实现代码分析
2010/06/05 Javascript
jQuery实战之品牌展示列表效果
2011/04/10 Javascript
js中 关于undefined和null的区别介绍
2013/04/16 Javascript
让html页面不缓存js的实现方法
2014/10/31 Javascript
JavaScript实现拖拽网页内元素的方法
2015/04/15 Javascript
JavaScript中split与join函数的进阶使用技巧
2016/05/03 Javascript
详解Vue自定义过滤器的实现
2017/01/10 Javascript
NodeJs安装npm包一直失败的解决方法
2017/04/28 NodeJs
浅谈webpack打包过程中因为图片的路径导致的问题
2018/02/21 Javascript
vue.js将时间戳转化为日期格式的实现代码
2018/06/05 Javascript
js实现微信聊天效果
2020/08/09 Javascript
vue+element table表格实现动态列筛选的示例代码
2021/01/14 Vue.js
Python基础知识_浅谈用户交互
2017/05/31 Python
疯狂上涨的Python 开发者应从2.x还是3.x着手?
2017/11/16 Python
wxPython的安装与使用教程
2018/08/31 Python
详解python selenium 爬取网易云音乐歌单名
2019/03/28 Python
Python3.6实现根据电影名称(支持电视剧名称),获取下载链接的方法
2019/08/26 Python
Python3与fastdfs分布式文件系统如何实现交互
2020/06/23 Python
西班牙英格列斯百货官网:El Corte Inglés
2016/09/25 全球购物
Lee牛仔裤澳大利亚官网:美国著名牛仔裤品牌
2017/09/02 全球购物
美国最大的旗帜经销商:Carrot-Top
2018/02/26 全球购物
Prototype如何为一个Ajax添加一个参数
2015/12/06 面试题
优秀员工表扬信
2014/01/17 职场文书
房屋买卖委托公证书
2014/04/08 职场文书
中药学专业求职信
2014/05/31 职场文书
大一工商管理职业生涯规划:有梦最美,行动相随
2014/09/18 职场文书
药店营业员岗位职责
2015/04/14 职场文书
2015年医院创卫工作总结
2015/04/22 职场文书
Mysql Show Profile
2021/04/05 MySQL
纯CSS实现hover图片pop-out弹出效果的实例代码
2021/04/16 HTML / CSS
只用40行Python代码就能写出pdf转word小工具
2021/05/31 Python