使用线程在 ZeroMQ REQ/REP 模式的服务器端制作许多回复套接字

Making many replier sockets in the server side of a ZeroMQ REQ/REP pattern, using threads

由于我的工作原因,使用 ZeroMQ REQ/REP 模式,我决定让服务器的回复者在与主体不同的线程中工作。我将展示的代码总结了这种方法:

import time
import zmq
import threading


def make_work(context):
    socket = context.socket(zmq.REP)
    socket.bind("tcp://*:5555")

    message = socket.recv()
    print("Received request: %s" % message)

    #Do some 'work'
    time.sleep(1)

    #Send reply back to client
    socket.send(b"World")
    socket.close()



 context = zmq.Context()
 thr = None

 while True:

    if not thr or not thr.is_alive():

        thr = threading.Thread(target = make_work, args = (context, ) )
        thr.start()

我修改了pyzmq指南的hello world示例。所以,我的问题是,当我 运行 来自 Pieter Hintjens 制作的文档的 hello world 客户端时,预期的行为是:对于我正在创建的每个线程,我打开的回复器套接字将答案发送到客户端,但真正的行为是,在第一个线程之后,连接的两侧都会阻塞。如果我在客户端进行投票,然后重试发送,就成功了,但这不是我想要的。是否有可能在服务器端,在新线程中成功接收?

Q : It is possible a successful receive in the server side, in the new thread?

是的,是的。

你的一半代码(客户端仍然不可见)效率很低。创建+设置+自行建立基础设施需要一些时间(重新实例化Socket-实例,配置其本地端,询问O/S 为 .bind() 提供端口,等待其他人成功检测到 .connect() 的新对手方的存在,并实际执行 .connect() 来回设置和协商 ling ...), 除了一条消息和 .close()?

所做的一切

好吧,如果有人愿意的话。

智能系统重复使用资源,无需为已经支付的内容支付两次,次数越少。


此外,您的无限循环 "re-instated" 线程会产生您在代码中看不到的额外副作用。除了上述所有系统性(但每次调用都重复)延迟之外,还有一个可能永远阻塞的延迟 - zmq.LINGER - 一个秘密阻塞器。

早期版本的 ZeroMQ API 使用默认值 zmq.LINGER == -1 - 能够在 .close() 方法上无限长地阻塞.较新的版本,当然是 v4.3-stable,使用 zmq.LINGER 默认值 1000 [ms]

无论如何,专业的设计明确控制实例参数并设置.setsockopt( zmq.LINGER, 0 )以确保安全,无一例外。

如果有兴趣,请随时阅读更多关于 REQ/REP 相互死锁的其他无声危险的更多详细信息 ZeroMQ posts