ZeroMQ模式用于基于空闲的工作负载平衡工作

Arn*_*sen 5 nonblocking asyncsocket zeromq

我有一个生产者和n个工人,我只想在他们还没有处理工作单元的时候工作,我很难找到一个好的零模式.

1)REQ/REP

生产者是请求者并创建与每个工作者的连接.它跟踪哪个工人忙碌,轮询闲置工人

问题:

  • 如何通知响应并仍然能够将新工作发送给空闲工作者而不将生产线中的线程专用于每个工作者?

2)按下/拉

生产者推入一个所有工作者都关闭的套接字,工作者进入生产者监听的另一个套接字.

问题:

  • 没有工人闲置的概念,即工作被困在长期工作单位之后

3)PUB/SUB

不首先,因为没有办法确保工作不会丢失

4)反向REQ/REP

每个工作者都是REQ结束,并从生产者请求工作,然后在完成工作时发送另一个请求

问题:

  • 制作人必须阻止工作请求,直到有工作(因为每个人recv都必须与a配对send).这可以防止工人完成工作
  • 可以使用单独的完成通道进行修复,但生产者仍需要一些轮询机制来检测新工作并保持在同一个线程上.

5)每个工人的配对

每个工人都有自己的PAIR连接,允许独立发送工作和收到结果

问题:

  • 相同的问题REQ/ REP与要求每个工人线程

尽管zeroMQ是非阻塞/异步的,但是我找不到允许我的代码同步的模式,而不是在许多专用线程中阻塞或者在更少的情况下轮询自旋循环.这对于zeroMQ来说不是一个好的用例吗?

小智 7

使用ZMQ指南中的负载平衡模式解决了您的问题.这一切都与流量控制有关,同时也能够发送和接收消息.生产者只会向闲置工人发送工作请求,而工人可以随时发送和接收其他消息,例如中止,关闭等.


baz*_*zza 6

推/拉是你的答案.

当您在ZeroMQ中发送消息时,最初发生的所有事情都是它位于等待传递到目标的队列中.成功传输后,它将从队列中删除.队列的长度有限,但可以通过更改套接字的高水位线来设置.

有一个/一些后台线程代表您管理所有这些,并且您对ZeroMQ API的调用只是向那个/那些线程发出指令.套接字连接两端的线程协作来编组消息的传输,即发送方不会发送消息,除非接收方可以接收消息.

考虑这在推/拉设置中意味着什么.假设你的一名拉工人落后了.它不会接受消息.这意味着发送给它的消息开始堆积,直到达到高水位线.ZeroMQ将不再向该拉工作者发送消息.实际上,ZeroMQ中的AFAIK是一个拉扯工作者,其队列比同类队列更加完整,但收到的消息更少,因此所有工作人员的工作量都是平均的.

那意味着什么?

只需发送消息.让0MQ为您排序.

虽然没有明确的标志说"已经很忙",但如果可以发送消息,那么这意味着某个拉动工作者能够仅仅因为它已经跟上工作量而接收它.因此,它最适合处理新消息.

有局限性.如果所有工作人员都已满,则不会发送任何消息,并且当您尝试发送另一条消息时,您会在推送中被阻止.你可以通过计算zmq_send()花了多长时间来发现它(似乎).

不要忘记网络

还需要考虑网络带宽问题.在推送中排队的邮件将以收件人使用的速率或网络速度(以较慢者为准)进行传输.如果您的网络基本上太慢,那么这就是错误的网络.

潜伏

当然,堆积在缓冲区中的消息代表延迟.这可以通过将高水位线设置得非常低来限制.

这不会解决高延迟问题,但它可以让你发现你有一个问题.如果拉动工人数量不足,低水位标记将导致信息发送失败/阻塞更快.

实际上我认为在ZeroMQ中它会阻止推/拉; 你必须在zmq_send()的调用中测量经过的时间,以发现事情是否已被装瓶.

想到Nanomsg?

Nanomsg是ZeroMQ的重启,其中一个人参与其中.我喜欢它的很多东西,最终我认为它将取代ZeroMQ.它有一些更通用的模式(PAIR适用于所有传输,与ZeroMQ不同).此外,模式本质上是源代码中的可插入组件,因此与ZeroMQ相比,开发和集成模式要简单得多.上有差异的讨论,在这里

Philisophical讨论

演员模特

ZeroMQ绝对属于Actor Model编程领域.消息被填充到队列/通道/套接字中,并且在某个未确定的时间点它们将在接收端出现以进行处理.

这种架构的危险在于,有可能在不知情的情况下发生死锁.

假设您有一个系统,其中消息在一系列进程中双向传递,例如以一种方式指示并导致另一种方式.其中一个进程可能会尝试发送消息,而收件人实际上也在尝试向其发送消息.

只有当队列不满时才可以工作,并且可以(暂时)吸收消息,让每个人都继续前进.

但是假设网络由于某种原因而短暂地变得有点繁忙,并且延迟了消息传输.然后消息发送可能会失败,因为已达到高水位线.哎呦!然后再也没有人向任何人发送任何东西了!

CSP

发明了一种名为Communicating Sequential Processes的Actor模型,以解决这个问题.它有一个限制; 根本没有缓冲消息.在收件人收到所有数据之前,任何进程都无法完成发送邮件.

这样做的理论结果是,可以在数学上分析系统设计并将其发音为无死锁.实际结果是,如果你构建了一个可以解锁的系统,它每次都会这样做.那真的不是那么糟糕; 它会出现在测试中,而不是在部署后.

奇怪的是,在Microsoft的任务并行库的文档中暗示了这一点,他们主张在实现更强大的应用程序的过程中将缓冲区长度设置为零.

这就像将ZeroMQ高水位标记设置为零,但在zmq_setsockopt()中,0表示默认值,而不是零值.默认值为非零...

CSP更适合实时应用程序.任何可用工作人员的短缺都会立即导致无法发送消息(因此您的系统知道它无法满足实时需求),而不会因为数据被套接字等吸收而导致延迟增加(这要困难得多)去探索).

不幸的是,我们拥有的几乎所有通信技术(以太网,TCP/IP,ZeroMQ,nanomsg等)都倾向于Actor Model.一切都有某种缓冲区,无论是NIC上的数据包缓冲区还是操作系统中的套接字缓冲区.

因此,要在现实世界中实施CSP,必须在现有传输之上实现流控制.这需要工作,而且效率稍低.但如果一个系统需要它,它绝对是你要走的路.

就个人而言,我很乐意看到0MQ和Nanomsg将其作为一种行为选择.