在试验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
类型套接字的行并观察更有效的负载平衡器。