ZeroMQ/ZMQ 推/拉模式的用处
Posted
技术标签:
【中文标题】ZeroMQ/ZMQ 推/拉模式的用处【英文标题】:ZeroMQ/ZMQ Push/Pull pattern usefulness 【发布时间】:2012-09-12 08:14:19 【问题描述】:在试验ZeroMQ
Push/Pull
(他们称之为Pipeline
)套接字类型时,我很难理解这种模式的实用性。它被称为“负载平衡器”。
给定一个服务器向多个工作人员发送任务,Push/Pull 将在所有客户端之间平均分配任务。 3 个客户端和 30 个任务,每个客户端获得 10 个任务:client1 获得任务 1、4、7、... client2、2、5、...等等。很公平。字面上地。
但是,在实践中,任务复杂性或客户端计算资源(或可用性)通常是非均匀混合的,那么这种模式就会被严重破坏。所有任务似乎都是提前安排好的,服务器不知道客户端的进度,甚至不知道它们是否可用。如果 client1 宕机,它的剩余任务不会发送给其他客户端,而是为 client1 排队。如果 client1 仍然关闭,则永远不会处理这些任务。相反,如果客户端处理其任务的速度更快,则它不会获得更多任务并保持空闲状态,因为它们仍然为其他客户端安排。
使用REQ/REP
是一种可能的解决方案;然后只将任务分配给可用资源。
所以我错过了什么吗?如何有效使用Push/Pull
?
有没有办法使用这种套接字类型来处理客户端、任务等的不对称性?
谢谢!
这是一个简单的 Python 示例:
# server
import zmq
import time
context = zmq.Context()
socket = context.socket(zmq.PUSH)
#socket = context.socket(zmq.REP) # uncomment for Req/Rep
socket.bind("tcp://127.0.0.1:5555")
i = 0
time.sleep(1) # naive wait for clients to arrive
while True:
#msg = socket.recv() # uncomment for Req/Rep
socket.send(chr(i))
i += 1
if i == 100:
break
time.sleep(10) # naive wait for tasks to drain
.
# client
import zmq
import time
import sys
context = zmq.Context()
socket = context.socket(zmq.PULL)
#socket = context.socket(zmq.REQ) # uncomment for Req/Rep
socket.connect("tcp://127.0.0.1:5555")
delay = float(sys.argv[1])
while True:
#socket.send('') # uncomment for Req/Rep
message = socket.recv()
print "recv:", ord(message)
time.sleep(delay)
在命令行上启动 3 个带有延迟参数的客户端(即 1、1 和 0.1),然后启动服务器,看看所有任务是如何均匀分布的。然后杀死其中一个客户端,看看它的剩余任务没有得到处理。
取消注释指示将其切换到Req/Rep
类型的套接字并观察更有效的负载平衡器。
【问题讨论】:
【参考方案1】:这不是负载均衡器,这是在 0MQ 文档中停留了一段时间的错误解释。要进行负载平衡,您必须从工作人员那里获取有关其可用性的一些信息。 PUSH 与 DEALER 一样,是循环分销商。它的原始速度和简单性很有用。您不需要任何形式的喋喋不休,只需将任务从管道中抽出,它们就会以网络可以处理的速度尽快分发给所有可用的工作人员。
当您执行大量小任务并且员工不常进出时,该模式很有用。该模式不适用于需要时间才能完成的大型任务,因为您需要一个仅将新任务发送给可用工作人员的队列。它还受到反模式的影响,如果客户端发送许多任务然后工作人员连接,第一个工作人员将获取 1,000 条左右的消息,而其他工作人员仍在忙于连接。
您可以通过多种方式创建自己的高级路由。查看指南中的 LRU 模式:在此,工作人员明确告诉代理“准备好”。您还可以进行基于信用的流量控制,这就是我在任何实际负载平衡情况下都会做的事情。它是 LRU 模式的推广。见http://hintjens.com/blog:15
【讨论】:
当工作人员确实失败时,是否有一种机制可以检测到这一点并恢复已分配但未发送的排队任务?类似于任务重新分配的超时。 如果你想检测失败的工人,你必须自己添加。这相对容易:收集所有结果,如果缺少一个,重新开始整个批次。失败很少见,这种简单粗暴的方法可以很好地处理它。 最后的链接坏了。以上是关于ZeroMQ/ZMQ 推/拉模式的用处的主要内容,如果未能解决你的问题,请参考以下文章
负载测试 ZeroMQ (ZMQ_STREAM) 以找到它可以处理的最大同时用户