pyzmq学习笔记
前言
使用过简单的python的ZMQ:server开启3个线程,client发送心跳包,如果服务端超过n秒没应答,则重新连接。
网上找的案例,server使用的zmq.device,但是一直不明白什么含义。
案例链接:http://nphard.me/2016/03/05/pyzmq-demo/
client使用了超时重连,传输数据时,如果server没有响应则重新连接并重新发送数据,这样会导致,客户端重复发送多条数据,被服务端接收处理,但是服务端并没有回复。(以下准备解释,但是没成功)
以下为参考网站,很多英文的看不懂。
http://pyzmq.readthedocs.io/en/latest/
http://zguide.zeromq.org/py:all
https://learning-0mq-with-pyzmq.readthedocs.io/en/latest/index.html
https://wizardforcel.gitbooks.io/zmq-guide/content/chapter1.html
具体细节参考的中文资料在对应目录内给出。
zmq的router和dealer是什么
网上有很多资料介绍zmq的几种模式,以下介绍req/rep应答模式。
首先确认一个概念:XREQ/XREP are aliases for ROUTER/DEALER. XREQ/XREP were used in ZeroMQ 2.x.
那么router和dealer是什么?直接上链接:
http://www.cnblogs.com/fengbohello/p/4743868.html
官网介绍了应答模式的几种区别:http://zguide.zeromq.org/py:chapter3
以下是自己的理解,如果有问题请留言,谢谢。

参考画图:https://stackoverflow.com/questions/23581172/what-is-zmq-router-and-zmq-dealer-in-python-zeromq
zmq的device
参考官方api:http://pyzmq.readthedocs.io/en/latest/api/zmq.devices.html
参考device详细介绍:http://pjwqq.iteye.com/blog/2260254
根据上图给出代码,运行device_func,frontend面向客户端(发起请求方),绑定router接收请求,device内部通过backend与服务端连接,dealer向服务端发起请求,并将数据传达给server。
所以流程就是这样:client (req) -----> router/dealer (queue) -----> server (rep)
device 和 server 端:通过多线程写在一起的。运行先后顺序是 1、device --- 2、server / client (随便哪一个先启动都会等待后启动连接,如果中途server异常,client需要超时重试, !!!!!^~^)
def device_func():
thread_num = 3
context = zmq.Context()
url_router = 'inproc://ping-server'
url_dealer = 'tcp://*:5559' # Socket do cliente
frontend = context.socket(zmq.ROUTER) # 或者是 zmq.ROUTER zmq.XREP
frontend.bind(url_dealer) # Socket do servidor
backend = context.socket(zmq.DEALER) # 或者是 zmq.DEALER zmq.XREQ
backend.bind(url_router) for i in range(1, thread_num + 1):
thread = threading.Thread(target=server_func, args=(i, url_router, context))
thread.start() # property找不到 Device()报错
zmq.device(zmq.QUEUE, frontend, backend) frontend.close()
backend.close()
context.term() def server_func(name, url_router, context):
print(">>> start %d %s" % (name, '.' * 50))
socket = context.socket(zmq.REP)
socket.connect(url_router)
while True:
try:
message = socket.recv()
r_data = msgpack.unpackb(message, encoding='utf-8')
print('server %d received:' % name, r_data) data = 'server %d send: %s' % (name, utils.time_now())
print(data)
s_data = msgpack.packb(data)
socket.send(s_data) except:
traceback.print_exc()
socket.close()
break
client端,连接device的frontend端(dealer):
def client2():
url_dealer = 'tcp://localhost:5559'
context = zmq.Context()
socket = context.socket(zmq.REQ) print("Collecting data from server…")
socket.connect(url_dealer)
pid = os.getpid()
i = 0
while 1:
i += 1
# data = input('\n>>:').strip()
data = ('send - msg%d' % i)
# print(data)
s_data = msgpack.packb(data.encode())
socket.send(s_data) ret = socket.recv()
r_data = msgpack.unpackb(ret, encoding='utf-8')
print('>>>received msg%d server info: %s \n' % (i, r_data))
以上一起理解了zmq的device、router、dealer。
官网指出:function  zmq.device(device_type, frontend, backend) Deprecated since version libzmq-3.2: Use zmq.proxy 取而代之的 zmq.proxy(frontend, backend, capture)
同时又有 class zmq.devices.Device(device_type=3, in_type=None, out_type=None) 测试了跑不起来
备注:
inproc 是zmq本地 进程/线程 的传输方式。可以自定义。
zmq的Polling
主要功能应该是 一个程序种需要建立多个socket连接时,需要接收数据,又要转发数据等。参考以下链接:
http://pjwqq.iteye.com/blog/2260791
我这里主要是使用到client的超时重试功能。重现客户端不断超时重试发送数据,服务端不断接收回复。数据大量冗余重复。
server:同上,不过加了一句 sleep:
time.sleep(6)
message = socket.recv()
client:
def conn_socket(url_dealer):
""" 建立socket连接"""
try: context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect(url_dealer) poller = zmq.Poller()
poller.register(socket, zmq.POLLIN) print('[%d] socket conn success' % os.getpid())
return socket, poller except:
traceback.print_exc() def close_socket(socket, poller):
""" 关闭socket连接"""
try:
socket.close()
poller.unregister(socket)
except:
traceback.print_exc() def client1():
""" """
url_dealer = 'tcp://localhost:5559'
socket, poller = conn_socket(url_dealer)
try: i = 0
while 1:
i += 1
# data = input('\n>>:').strip()
data = 'msg%d' % i
print('send:%s' % data)
# print(data)
s_data = msgpack.packb(data.encode())
socket.send(s_data) while True:
# 超时后重新连接,参数是毫秒
if poller.poll(5 * 1000):
ret = socket.recv()
r_data = msgpack.unpackb(ret, encoding='utf-8')
print('>>>received:%s' % r_data)
break
else:
close_socket(socket, poller)
socket, poller = conn_socket(url_dealer) print('*resend:%s' % data)
socket.send(s_data) except Exception as e:
traceback.print_exc()
finally:
close_socket(socket, poller)
pass
注意看:我故意将server的sleep值 > client 的超时重试的值,那么问题就重现了:
客户端不停的连接重试重发数据:

服务端不停的接收回复:

看了官方文档的后续的更多的高级功能介绍,发现并没有找到解决方案,暂时智能把超时时间设置的足够大一些,并在返回数据中添加一个状态,重试1次加一个1,方便反查和监控报警。
pyzmq学习笔记的更多相关文章
- js学习笔记:webpack基础入门(一)
		之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ... 
- PHP-自定义模板-学习笔记
		1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ... 
- PHP-会员登录与注册例子解析-学习笔记
		1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ... 
- 2014年暑假c#学习笔记目录
		2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ... 
- JAVA GUI编程学习笔记目录
		2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ... 
- seaJs学习笔记2 – seaJs组建库的使用
		原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ... 
- CSS学习笔记
		CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ... 
- HTML学习笔记
		HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ... 
- DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记
		今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ... 
随机推荐
- Day053--MySQL
			MySQL安装和基本管理https://www.cnblogs.com/majj/p/9160383.html 管理员模式运行cmd 打开终端,输入mysqld,打开服务端. 打开终端,输入mysql ... 
- Grains 与 Pillars
			Grains 与 Pillars Grains介绍 Grains接口是salt用来采集底层系统信息的,包含了操作系统信息.域名.IP地址.内核.内存等一些底层信息.就是因为grains采集了这些信息, ... 
- 退役之战- SDOI
			嘻嘻, 从文化课中逃脱出来, 很痛苦啊, 英语已经近半年没学了,语文水平水的一批,在其他班里受虐待. 百废待兴. 因为曾经学了一段时间的省选,所以被老师拉回来送人头考试啦. 听说4.5 SDOI一轮哎 ... 
- Python学子之如何退出python 命令行
			python命令行是新手学习python过程中必须要学的一个工具,下面我们来看一下怎么退出python命令行. 工具/原料 python2.7 方法/步骤 1.我们这里使用的是python3.6版本, ... 
- 分析web.xml
			<?xml version="1.0" encoding="UTF-8"?> //xml的版本:1.0 和 编码:utf-8 <web-ap ... 
- 支持向量机SVM原理_python sklearn建模乳腺癌细胞分类器(推荐AAA)
			项目合作联系QQ:231469242 sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?cours ... 
- 编写高质量的Python代码系列(五)之并发与并行
			用Python可以很容易就能写出并发程序,这种程序可以在同一时间做许多间不同的事情.我们也可以通过系统调用.子进程(subprocess)及C语言扩展来实现并行处理. 第三十六条: 用subproce ... 
- Haproxy 安装及配置
			Haproxy介绍 HAProxy是一个特别适用于高可用性环境的TCP/HTTP开源的反向代理和负载均衡软件.实现了一种事件驱动,单一进程模型,支持非常大的并发连接,是因为事件驱动模型有更好的资源和时 ... 
- 01-oracle学习环境配置
			1.安装oracle与SQL Developer oracle10g安装教程 2.创建表空间以及用户 表空间是存储数据文件的容器,由数据文件组成,数据库的所有系统数据和用户数据都必须存储在数据文件中. ... 
- nginx  容器反向代理网址的设置
			先讲一下场景: nginx 容器要和SpringBoot 容器部署在一台机器上, nginx 为 SpringBoot 提供反向代理, 需要在 nginx.conf 中写上 SpringBoot 的 ... 
