【问题标题】:Using ZeroMQ to send replies to specific clients and queue if client disconnects如果客户端断开连接,使用 ZeroMQ 将回复发送到特定客户端和队列
【发布时间】:2015-10-23 08:32:11
【问题描述】:

我是 ZeroMQ 的新手,并试图找出一个设计问题。我的场景是我有一个或多个客户端向单个服务器发送请求。服务器将处理请求,做一些事情,并向客户端发送回复。有两个条件:

  • 回复必须发送给发送请求的客户端。
  • 如果客户端断开连接,服务器应该将消息排队一段时间,以便客户端重新连接时,它可以接收它错过的消息。

我很难找出最简单的方法来实现它。

我尝试过的事情:

  • PUB/SUB - 我可以用主题标记回复,以确保只有发送请求(以主题作为标识符)的订阅者才能收到正确的回复。这解决了路由问题,但由于发布者不知道订阅者,它对断开连接的客户端一无所知。

  • PUSH/PULL - 似乎能够处理消息队列问题,但看起来它不支持我将消息发送到特定客户端的计划(例如,基于他们的 ID)。

  • ROUTER/DEALER - 设计似乎是两者的解决方案,但所有示例似乎都相当复杂。

我现在的想法是继续PUB/SUB,尝试在客户端实现某种心跳(让服务器检测到客户端的存在),当客户端不再发送心跳时,它会停止发送带有其主题的消息。但这似乎不是最理想的,并且还会涉及另一个套接字。

对于我可能采取的任何其他实施方式,有什么想法或建议吗?任何信息,将不胜感激。我正在使用 Python,但任何语言都可以。

【问题讨论】:

  • 阅读 ZMQ 指南,特别是 chapter 4 on reliable request/reply patterns,看看这些设计是否适合您的用例。对于您提到的规格,我几乎肯定会使用 ROUTER/DEALER,特别是它是您提到的唯一一种不打算单向的套接字类型。不要害怕复杂性,学习曲线不是那么陡峭,并且不要害怕额外的套接字如果你需要它们(你可能不需要)。
  • ... 此外,如果您在链接的章节中找到一个 close 但以某些方式倒下的示例,那么有人可以更轻松地为您指明正确的方向解决这些缺点。

标签: zeromq pyzmq


【解决方案1】:

要为您的解决方案准备最佳建议,请提供有关您的应用需求的更多数据。我对您的情况做了一些研究,并结合我对 ZMQ 的经验,在这里我提出两种可能性:

1)两个方向的PUSH/PULL模式,对扩展性影响较大,但来自服务器的消息会被缓存。

服务器有一个 PULL 套接字来注册每个客户端并从客户端获取所有消息。每条消息都应该有客户端 ID,以便服务器了解发送响应的位置。

为每个客户端 - 服务器创建 PUSH 套接字以发送响应。套接字配置在注册消息中发送。您还可以对注册客户端使用 REQ/REP 模式(分配套接字号)。

每个客户端都有自己的PULL套接字,该套接字的配置在注册消息中发送到服务器。

这意味着具有三个客户端的服务器需要(例如 [] 中的端口号):

  • 服务器:1 x PULL[5555] 套接字,3 x PUSH[5560,5561,5562] 套接字(+ 可选 1 X REQ[5556] 套接字用于注册,但我认为这取决于您如何准备客户端身份)
  • 客户端:1 x PUSH[5555] 套接字,1 x PULL[5560|5561|5562](每个客户端一个)(+ 可选 1 X REP[5556]

您必须将服务器连接到多个客户端套接字才能发送响应,但如果客户端断开连接,消息不会丢失。客户端在重新连接到他们的 PULL 套接字时会收到他们自己的消息。缺点是需要在服务器端创建很少的 PUSH 套接字(客户端数量)。

2) PUB/SUB + PUSH/PULL 或 REQ/REP,服务器端的静态 cocket 配置(只有 2 个),但服务器必须准备一些机制来重传或缓存消息。 p>

服务器创建PUB 套接字和PULLREQ。客户端通过PULLREQ 套接字注册它的身份。服务器将使用此身份作为过滤器向客户端发布所有消息。服务器使用PUB 套接字上的monitor() 函数来计算连接和断开连接的客户端的数量(操作:'accept' 和'disconnect')。在“断开连接”后,操作服务器向所有客户端发布消息以再次注册。对于未重新注册的客户端,服务器停止发布消息。

客户端创建SUB套接字和PUSHREQ来注册和发送请求。

此解决方案可能需要在服务器端进行一些缓存。客户端可以在从 SUB 套接字获取每条消息后对其进行确认。它更复杂,必须与您的要求联系起来。如果您只是想知道该客户丢失了消息。客户端可以在注册期间发送从服务器接收到的最后一条消息的时间戳。如果您需要保证客户端获得所有消息,则需要一些缓存实现。可能是订阅所有消息并删除客户端确认的每个消息的其他进程。

在此解决方案服务器中,需要三个客户端([] 中的示例端口号):

  • 服务器:1 x PUB[5555] 套接字,1 x REPPULL[5560] 套接字 + 监控 PUB 套接字
  • 客户端:1 x SUB[5555] 套接字和自己的过滤器标识,1 x REQPUSH[5560] 套接字

关于监控你可以在这里阅读:https://github.com/JustinTulloss/zeromq.node#monitoring(NodeJS 实现,但 Python 会类似)


我考虑过其他模式,但我不确定ROUTER/DEALERREQ/REP 是否能满足您的要求。您应该阅读有关模式的更多信息,因为每种模式都更适合某些解决方案。看这里:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 2020-10-13
    • 2017-11-04
    • 2021-12-05
    相关资源
    最近更新 更多