【问题标题】:What's the most efficient way to async send data while async receiving with 0MQ?使用 0MQ 异步接收时异步发送数据的最有效方法是什么?
【发布时间】:2019-08-06 09:16:07
【问题描述】:

我有一个 ROUTER/DEALER 设置,只要数据可用,两端就需要能够异步接收和发送数据。该模型几乎是 0MQ 的异步 C++ 服务器:http://zguide.zeromq.org/cpp:asyncsrv

客户端和服务器工作人员都会轮询,当有可用数据时,他们会调用回调。发生这种情况时,从另一个线程(!)我将数据放入std::deque。在每个 poll-forever 线程中,我检查deque(处于锁定状态),如果那里有项目,我将它们发送到指定的 DEALER id(id 放在队列中)。

但我不禁认为这不是惯用的 0MQ。互斥锁可能是一个设计问题。此外,如果轮询之间经过足够的时间(并且数据在deque 中累积),内存消耗可能会变得相当高。

我能想到的唯一选择是每次我想发送数据时让另一个 DEALER 线程连接到inproc,然后让它发送并退出。但是,这意味着每个发送的数据项都要连接 + 套接字的构造和销毁,这可能并不理想。

有没有惯用的 0MQ 方法来做到这一点,如果有,它是什么?

【问题讨论】:

  • 在给定 nCPU 核心 [1] 和此类进程可分配 RAM [GB] 的情况下,您的目标延迟 [us] 和数据有效负载大小 [B] + 峰值吞吐量节奏 [Hz] 是多少?
  • 我还没有确切的要求,我只是对我当前的设计是否干净与 0MQ 设计理念(如果我正在阅读,这似乎完全不鼓励锁定)感兴趣正确)。

标签: c++ zeromq


【解决方案1】:

我不完全理解您的设计,但我理解您对使用锁的担忧。

在大多数情况下,您可以使用 zeromq PAIR 套接字和 inproc 重新设计代码以消除对锁的使用。

你真的需要一个 std::deque 吗?如果不是,您可以只使用 zerom 队列,因为它只是一个可以使用套接字从不同线程读取/写入的队列。

如果您确实需要双端队列,则将其封装到自己的线程中(一个类会很好),并使其 API(推送等)可通过 inproc 套接字访问。

所以就像我之前说的那样,我可能走错了路,但在我遇到的 99% 的情况下,如果你需要信号,你总是可以用一些 ZMQ_PAIR/inproc 完全删除锁。

【讨论】:

    【解决方案2】:

    0mq 队列的缓冲区大小有限,可以控制。所以内存问题会达到一定程度,然后会发生数据丢失。出于这个原因,您可以考虑使用 conflate 选项,只在队列中保留最近的数据。

    在单台服务器和多线程单机通信的情况下,我建议使用发布/订阅模型,其中使用 conflate 选项,您将在读取缓冲区后立即收到新数据,而不必担心内存。它消除了阻塞队列问题。

    至于你的实现,你是对的,它不是最好的设计,但它是不可避免的。我建议在回答您的问题时检查问题Access std::deque from 3 threads,这可能不是最好的方法。

    【讨论】:

    • 感谢您的回答,但这不是我要问的。我确实知道如何从多个线程安全地访问deque,而切换到 PUB/SUB 并不能解决我要问的问题。
    • 那是0MQ的问题吗?
    • 我真的只是在问,鉴于 ROUTER/DEALER 设置,是像我现在做的那样做更好还是我应该有另一个线程connect()(并为每次发送创建/销毁一个套接字)。或者,如果有其他方式(同样,使用 ROUTER/DEALER)。
    猜你喜欢
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多