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生成随机数的方法
Jan 14 Python
python中urllib模块用法实例详解
Nov 19 Python
python的numpy模块安装不成功简单解决方法总结
Dec 23 Python
解决Python下imread,imwrite不支持中文的问题
Dec 05 Python
python装饰器简介---这一篇也许就够了(推荐)
Apr 01 Python
pycharm访问mysql数据库的方法步骤
Jun 18 Python
Python 日志logging模块用法简单示例
Oct 18 Python
python GUI库图形界面开发之PyQt5 MDI(多文档窗口)QMidArea详细使用方法与实例
Mar 05 Python
JupyterNotebook 输出窗口的显示效果调整方法
Apr 13 Python
python3中calendar返回某一时间点实例讲解
Nov 18 Python
Python 实现集合Set的示例
Dec 21 Python
python 装饰器的基本使用
Jan 13 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
咖啡的传说和历史
2021/03/03 新手入门
PHP+SQL 注入攻击的技术实现以及预防办法
2011/01/27 PHP
php提示Call-time pass-by-reference has been deprecated in的解决方法[已测]
2012/05/06 PHP
PHP中替换换行符的几种方法小结
2012/10/15 PHP
解析:通过php socket并借助telnet实现简单的聊天程序
2013/06/18 PHP
php-fpm开启状态统计的方法详解
2017/06/23 PHP
javascript 面向对象全新理练之数据的封装
2009/12/03 Javascript
基于jQuery实现左右div自适应高度完全相同的代码
2012/08/09 Javascript
jQuery获取选中内容及设置元素属性的方法
2014/07/09 Javascript
javascript实现表单提交后,提交按钮不可用的方法
2015/04/18 Javascript
JavaScript实现列表分页功能特效
2015/05/15 Javascript
浅谈Javascript数组索引
2015/07/29 Javascript
jQuery Mobile开发中日期插件Mobiscroll使用说明
2016/03/02 Javascript
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
2016/05/03 Javascript
针对后台列表table拖拽比较实用的jquery拖动排序
2016/10/10 Javascript
Angular 2应用的8个主要构造块有哪些
2016/10/17 Javascript
AngularJS入门教程之数据绑定原理详解
2016/11/02 Javascript
微信小程序学习笔记之登录API与获取用户信息操作图文详解
2019/03/29 Javascript
node省市区三级数据性能测评实例分析
2019/11/06 Javascript
js实现验证码干扰(静态)
2021/02/22 Javascript
[02:00]DOTA2英雄COSPLAY闹市街头巡游助威2015国际邀请赛
2015/08/02 DOTA
python关键字and和or用法实例
2015/05/28 Python
Python批量更改文件名的实现方法
2017/10/29 Python
python将回车作为输入内容的实例
2018/06/23 Python
python用quad、dblquad实现一维二维积分的实例详解
2019/11/20 Python
Win系统PyQt5安装和使用教程
2019/12/25 Python
python爬虫把url链接编码成gbk2312格式过程解析
2020/06/08 Python
Ubuntu16安装Python3.9的实现步骤
2020/12/15 Python
Python数据模型与Python对象模型的相关总结
2021/01/26 Python
英国高档时尚男装购物网站:MR PORTER
2016/08/09 全球购物
高中毕业生自我鉴定例文
2013/12/29 职场文书
政风行风评议心得体会
2014/10/21 职场文书
2015年人力资源工作总结
2015/04/08 职场文书
你为什么是穷人?可能是这5个缺点造成
2019/07/11 职场文书
Pytorch反向传播中的细节-计算梯度时的默认累加操作
2021/06/05 Python
redis复制有可能碰到的问题汇总
2022/04/03 Redis