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计算程序开始到程序结束的运行时间和程序运行的CPU时间
Nov 28 Python
Python打印斐波拉契数列实例
Jul 07 Python
Python简单读取json文件功能示例
Nov 30 Python
Python实现将MySQL数据库表中的数据导出生成csv格式文件的方法
Jan 11 Python
python2.x实现人民币转大写人民币
Jun 20 Python
python3 对list中每个元素进行处理的方法
Jun 29 Python
python 中的列表生成式、生成器表达式、模块导入
Jun 19 Python
Python将文字转成语音并读出来的实例详解
Jul 15 Python
Python matplotlib绘制饼状图功能示例
Sep 10 Python
Python函数式编程指南:对生成器全面讲解
Nov 19 Python
Python中常用的高阶函数实例详解
Feb 21 Python
Python join()函数原理及使用方法
Nov 14 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
ASP和PHP都是可以删除自身的
2007/04/09 PHP
php中邮箱地址正则表达式实现与详解
2012/04/24 PHP
zf框架db类的分页示例分享
2014/03/14 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
Laravel如何同时连接多个数据库详解
2019/08/13 PHP
Thinkphp5.0框架的Db操作实例分析【连接、增删改查、链式操作等】
2019/10/11 PHP
如何使用Javascript正则表达式来格式化XML内容
2013/07/04 Javascript
Jquery解析Json格式数据过程代码
2014/10/17 Javascript
js实现鼠标滚轮控制图片缩放效果的方法
2015/02/20 Javascript
JS+CSS实现类似QQ好友及黑名单效果的树型菜单
2015/09/22 Javascript
基于jQuery实现带动画效果超炫酷的弹出对话框(附源码下载)
2016/02/22 Javascript
javascript html5摇一摇功能的实现
2016/04/19 Javascript
AngularJS Phonecat实例讲解
2016/11/21 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
2017/08/19 Javascript
详解vue中router-link标签所必备了解的属性
2019/04/15 Javascript
使用webpack4编译并压缩ES6代码的方法示例
2019/04/24 Javascript
详解JS实现系统登录页的登录和验证
2019/04/29 Javascript
原生js实现文件上传、下载、封装等实例方法
2020/01/05 Javascript
[49:31]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS BO3 第二场 1月29日
2021/03/11 DOTA
Python编程中字符串和列表的基本知识讲解
2015/10/14 Python
在Python的Flask中使用WTForms表单框架的基础教程
2016/06/07 Python
Java及python正则表达式详解
2017/12/27 Python
PyCharm代码整体缩进,反向缩进的方法
2018/06/25 Python
Python subprocess模块功能与常见用法实例详解
2018/06/28 Python
python 修改本地网络配置的方法
2019/08/14 Python
喜诗官方在线巧克力店:See’s Candies
2017/01/01 全球购物
KIKO MILANO俄罗斯官网:意大利领先的化妆品和护肤品品牌
2021/01/09 全球购物
师范应届生教师求职信
2013/11/05 职场文书
给校长的建议书400字
2014/05/15 职场文书
幽默自我介绍演讲稿
2014/08/21 职场文书
离职证明范本(5篇)
2014/09/19 职场文书
2014年银行工作总结范文
2014/11/12 职场文书
民事上诉状范文
2015/05/22 职场文书
成事在人观后感
2015/06/16 职场文书
经营场所证明范本
2015/06/19 职场文书