无法使用 python 3.7 运行 ZMQStream 和 Tornado 事件循环

Unable to run ZMQStream with Tornado Event loop using python 3.7

我一直在尝试使用 zmq eventloop 为 REQ / REP 消息传递设置服务器/客户端。由于 python 3 不支持 zmq 提供的事件循环,我正在尝试 运行 它与 tornado 的事件循环。

我在使用 python 3.

将 zmqStream 与龙卷风的事件循环结合使用时遇到问题 运行

我使用 zmq 的 zmqStream 和 tornado 的事件循环创建了服务器/客户端代码。客户端正在发送正确的消息,但服务器似乎没有响应消息请求。

服务器端代码:

from tornado import ioloop
import zmq

def echo(stream, msg):
   stream.send_pyobj(msg)

ctx = zmq.Context()
socket = ctx.socket(zmq.REP)
socket.bind('tcp://127.0.0.1:5678')
stream = ZMQStream(socket)
stream.on_recv(echo)
ioloop.IOLoop.current().start()

客户端代码:

import zmq

context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:5678")

for request in range (1,10):
   print("Sending request ", request,"...")
   socket.send_string("Hello")
   # Get the reply.
   message = socket.recv_pyobj()
   print("Received reply ", request, "[", message, "]")

我期待服务器 return 返回客户端发送的请求消息。但它只是不响应正在发送的请求。

Q : server doesn't seem to be responding


第 0 步:

一个服务器端 SLOC,stream = ZMQStream( socket ) 调用一个函数,该函数未被 MCVE 记录并且必须并且确实无法执行以产生任何结果:"ZMQStream" in dir() 通过 [=47= 确认了这一点]False

解决方法: 修复 MCVE 并 print( zmq.zmq_version ) + "ZMQStream" in dir() 确认


第 1 步:

始终防止无限死锁,除非存在不这样做的正当理由,在执行相应的 .bind().connect() <aSocket>.setsockopt( zmq.LINGER, 0 )[=55= 之前进行设置].永远挂起的应用程序和未释放的(是的,你没看错,无限阻塞)资源在分布式计算系统中是不受欢迎的。


第 2 步:

避免盲目的分布式互锁死锁 REQ/REP 总是很容易陷入 运行。它会发生,只是永远不知道什么时候。您可以在 Stack Overflow 上阅读大量关于此的详细信息。

还有补救措施?可以(并且应该,在可能的情况下)避免使用 .recv()-s 的阻塞形式(公平的 .poll()-s 是更智能的设计方式,资源方式)可以使用额外的发送方信号在将任何一方“扔”到无限阻塞 .recv()-s 之前(但是网络传输失败或其他原因导致静默消息丢失可能会导致软信号发送以标记发送,这不会导致接收和相互死锁,其中硬连线行为使 REQ/REP 双方都进入等待对方的状态,以发送消息(交易对手永远不会发送,因为它也在等待 .recv()-ing 静止没有收到对面(还在听)的))


最后但同样重要的是:

ZeroMQ Zen-of-Zero 也有零保证——因为消息要么完全传递(无错误)要么根本不传递。 REQ/REP 相互死锁是最好解决的,如果一个人永远不会陷入僵局(参考上文 LINGERpoll()