ZeroMQ 非阻塞非队列推送

Posted

技术标签:

【中文标题】ZeroMQ 非阻塞非队列推送【英文标题】:ZeroMQ Non-Blocking Non-Queueing Push 【发布时间】:2012-12-11 20:57:54 【问题描述】:

我正在使用 ZeroMQ 的 C# 包装器,但这似乎更像是 ZeroMQ 的一个潜在问题。

有没有什么方法可以在不阻塞而不排队的情况下推送消息?如果服务器未启动,我希望将消息永久处理而不会阻塞。

以下是我目前尝试过的设置:

1)

发送(阻止发送)

高水位线 = 0

这(奇怪地)没有阻塞,但它似乎在内存中排队,直到套接字连接(内存不断增加进程)。

2)

发送(非阻塞发送)

高水位线 = 1

这是一个竞争条件。如果我快速连续发送两条消息,则有时会因为超过高水位线而丢弃一条消息。

3)

轮询套接字以确定它是否会阻塞。这并没有真正帮助,因为我仍然必须在队列开始阻塞之前将一条(旧)消息放入队列(如果我设置 HWM = 1)。

具有任何高水位标记的非阻塞发送是不可取的,因为一旦服务器恢复联机,它就会从客户端收到一堆旧消息。

阻止发送不起作用,因为我不想阻止。

【问题讨论】:

【参考方案1】:

您似乎在寻找的只是一个 PUB 套接字。此套接字类型在发送时从不阻塞,并丢弃它无法发送给订阅者的任何消息。请参阅此页面:http://api.zeromq.org/3-2:zmq-socket。

附带说明一下,您不需要将此套接字用于“真正的”发布/订阅,您可以通过端点只有一个 PUB 和一个 SUB 套接字,将其用于两个节点之间的非阻塞通信。 您的服务器在重新连接后不会收到“旧”消息,因为 PUB 套接字将丢弃在服务器断开连接时无法发送的消息。尽管如此,我相信虽然您无法避免一些内部 ZMQ“排队”,但它应该对您的用例影响不大。

【讨论】:

这在消息持久性方面显然是一种改进。不幸的是,我的系统是这样的,我有多个发送者和一个接收者,这似乎与没有很多 hackery 的 PUB/SUB 不兼容。 大量骇客?并非如此,您可以做的是绑定订阅者(服务器),并将所有发布者(工作者)连接到同一个端点。确保仅在连接完成后才发送消息(否则您可能会丢失一些消息) 啊,直到我仔细阅读后才知道任何一方都可以绑定/连接。这与我上面的#2 有何不同?那也没有阻挡。问题是,当我将高水位标记设置为低(我不想建立旧消息)时,即使连接了套接字,它最终也会抛出消息。我目前的解决方案是为每条消息发送一个时间戳,并丢弃旧消息(大概是卡在消息队列中的消息)。但我真的不想为每条消息序列化/反序列化时间戳。 在这种情况下为什么要设置低 HWM? (并且我假设像你的例子一样,即 如果我理解如果没有立即收到消息是陈旧的,但是 ZMQ 架构会尽可能快地推送它们,即使有一些“排队”正在进行(这实际上对你有好处因为它批处理消息)。即使您使用原始套接字,您可能仍然需要检查一些时间戳以查看消息是否太旧(我在这里假设毫秒/微秒延迟),因为您无法真正“控制”网络延迟。

以上是关于ZeroMQ 非阻塞非队列推送的主要内容,如果未能解决你的问题,请参考以下文章

并发阻塞队列和非阻塞队列详解

阻塞队列与非阻塞队列

阻塞队列

嵌入式Linux开发27——Linux阻塞和非阻塞IO

非阻塞队列

阻塞与非阻塞