用于寻址异步请求的ZMQ Python请求-应答代理
我想利用ZMQ(在python中)实现一个代理和一个客户端,该代理和客户端异步处理对寻址实体的请求-应答。客户端包含执行请求和应答的功能(唯一缺少的是确切的套接字类型/模式) 请求可以是阻塞的,但是应答端需要能够在并行(线程化)请求进入时处理它们。(ie REP socket不够好,因为它需要在下次接收之前发送) 它需要通过代理,因为可能有许多实体可以执行请求和回复,我只想绑定一组端口(不是每个实体一个) Entity1将知道Entity2的ID,并使用该ID确保该请求是专门向Entity2发出的。可以有任意数量的实体,但所有响应请求的实体都将注册ID 我已经尝试过在上面的代理右侧使用DEALER,但它似乎只会循环发送请求 那么,有人知道我可以使用一个好的模式/套接字集来异步寻址特定的实体吗 总结:用于寻址异步请求的ZMQ Python请求-应答代理,python,request,zeromq,broker,reply,Python,Request,Zeromq,Broker,Reply,我想利用ZMQ(在python中)实现一个代理和一个客户端,该代理和客户端异步处理对寻址实体的请求-应答。客户端包含执行请求和应答的功能(唯一缺少的是确切的套接字类型/模式) 请求可以是阻塞的,但是应答端需要能够在并行(线程化)请求进入时处理它们。(ie REP socket不够好,因为它需要在下次接收之前发送) 它需要通过代理,因为可能有许多实体可以执行请求和回复,我只想绑定一组端口(不是每个实体一个) Entity1将知道Entity2的ID,并使用该ID确保该请求是专门向Entity2发出
- 请求端阻塞
- 用于绑定固定号码的代理/代理 港口
- 应答套接字应由 请求者
- 线程回复(回复端可以接收和处理 并行请求)
我已经非常广泛地阅读了ZMQ手册,但是我还没有找到通过代理解决特定套接字的任何真正好的模式,因此非常感谢您的帮助。经过进一步的研究和测试,我发现了一种模式,似乎可以为我的所有需求提供解决方案 模式
Requester Broker Replier
REQ ------------- ROUTER ROUTER -------------- DEALER
(requests) (replies)
请求者
if self.reqRouterSocket in socketEvents:
multipart = self.reqRouterSocket.recv_multipart()
multipart = [multipart[-2]] + multipart
del multipart[-2]
self.repRouterSocket.send_multipart(multipart)
客户端的请求端只需连接到代理上的请求路由器,发送请求并开始读取套接字以获得回复:
reqSocket.connect(self._reqAddress)
reqSocket.send_multipart([repId, message])
reply = reqSocket.recv_multipart()[0]
回复者ID包含在邮件的第一部分,例如:
Outgoing message: ['replierId', 'requestMsg']
请求路由器
if self.reqRouterSocket in socketEvents:
multipart = self.reqRouterSocket.recv_multipart()
multipart = [multipart[-2]] + multipart
del multipart[-2]
self.repRouterSocket.send_multipart(multipart)
也就是说,请求路由器只移动有效负载的第一部分(即replierId),并将其放在地址堆栈的第一位:
Incoming message: ['reqSocketAddr', '', 'replierId', 'requestMsg']
Outgoing message: ['replierId', 'reqSocketAddr', '', 'requestMsg']
传出消息从应答器路由器发送。由于应答器已将其套接字id设置为“replierId”,并已连接到应答器路由器,因此该路由器可识别此地址,并能够成功传递请求
回复者
if self.reqRouterSocket in socketEvents:
multipart = self.reqRouterSocket.recv_multipart()
multipart = [multipart[-2]] + multipart
del multipart[-2]
self.repRouterSocket.send_multipart(multipart)
应答器需要将其自己的套接字标识设置为某个已知值,以便如上所述直接寻址
注意:在执行连接到应答路由器之前,必须设置经销商插座的插座id。要设置套接字的标识,请执行以下操作:
self.dealerSocket.setsockopt(zmq.IDENTITY, 'replierId')
否则,路由器将不知道id,并将抛出消息
应答器侦听传入的请求。在我的例子中,这都是线程化的,请求是异步处理的。这就是使用经销商插座而不是常规维修的原因,在同步情况下,这会容易得多。经销商插座可以接收更多请求,而无需先回答第一个请求,而代表必须回答第一个请求。不过,回复方所做工作的简化版本是:
multipart = self.dealerSocket.recv_multipart()
returnRoute = multipart[:-1]
requestMsg = multipart[-1]
reply = someFunction(requestMsg)
self.dealerSocket.send_multipart(returnRoute + [reply])
也就是说,应答器只返回它得到的内容,但请求更改为应答:
Incoming message: ['replierId', 'reqSocketAddr', '', 'request']
Outgoing message: ['replierId', 'reqSocketAddr', '', 'reply']
然后将该传出消息发送回应答路由器
应答路由器
if self.reqRouterSocket in socketEvents:
multipart = self.reqRouterSocket.recv_multipart()
multipart = [multipart[-2]] + multipart
del multipart[-2]
self.repRouterSocket.send_multipart(multipart)
在代理的这一边选择路由器纯粹是因为它需要在许多连接的套接字中寻址特定套接字的功能
if self.repRouterSocket in socketEvents:
multipart = self.repRouterSocket.recv_multipart()
self.reqRouterSocket.send_multipart(multipart[1:])
也就是说,只需弹出地址堆栈的第一个地址,并将消息再次发送到请求方即可
Incoming message: ['replierId', 'reqSocketAddr', '', 'reply']
Outgoing message: ['reqSocketAddr', '', 'reply']
请求路由器识别该地址并将请求发送回请求者,请求者接收:
Incoming list: ['reply']
这个模式似乎满足了我在问题中提出的要求。我希望它也能对其他人有用。谢谢!我也面临同样的问题,你的回答帮助了我。