ZeroMQ推/拉模式的用处
在试用ZeroMQ
Push/Pull
(他们称为Pipeline
)套接字types时,我很难理解这种模式的效用。 它被称为“负载平衡器”。
如果一个服务器向多个工作人员发送任务,推/拉将在所有客户端之间平均分配任务。 3个客户端和30个任务,每个客户端获得10个任务:客户端1获取任务1,4,7,…客户端2,2,5,…等等。 很公平。 从字面上看。
但是,实际上,任务复杂性或客户端计算资源(或可用性)往往是非均匀混合的,那么这种模式就会严重破坏。 所有的任务似乎都是预先安排好的,服务器不知道客户的进展情况,甚至是否可用。 如果client1发生故障,其剩余任务不会发送到其他客户端,而是保持排队等待client1。 如果client1保持closures状态,那么这些任务不会被处理。 相反,如果一个客户在处理任务时更快,那么他就没有得到更多的任务,并保持闲置状态,因为他们仍然为其他客户安排。
使用REQ/REP
是一种可能的解决scheme; 任务然后只被赋予一个可用的资源。
所以我错过了什么? Push/Pull
如何有效使用? 有没有办法处理这种套接字types的客户端,任务等的不对称?
谢谢!
以下是一个简单的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)
在命令行(即1,1和0.1)和服务器上启动3个带延迟参数的客户机,看看所有的任务是如何均匀分配的。 然后杀死其中一个客户端,看看其余的任务没有被处理。
取消注释指示的行将其切换到Req/Rep
types套接字,并观察更有效的负载平衡器。
这不是一个负载平衡器,这是一个错误的解释,一直停留在0MQ文档。 要进行负载平衡,您必须从工作人员那里获得有关其可用性的一些信息。 像经销商一样,PUSH是一个循环的分销商。 它的原始速度和简单性非常有用。 您不需要任何forms的喋喋不休,只需将任务从pipe道中抽出,然后以networking可以处理的速度将其喷射到所有可用的工作人员身上。
这个模式在你做很多小任务时很有用,而且工作人员经常出入。 该模式对于需要时间完成的较大任务来说并不合适,因为那时您需要一个将新任务仅发送给可用工作人员的队列。 如果客户端发送很多任务,然后工作人员连接,第一名工作人员就会抓取1000条左右的消息,而其他人仍然忙于连接。
您可以通过多种方式创build自己的高级路由。 看看指南中的LRU模式:在这个工作人员明确告诉经纪人“准备好”。 你也可以做基于信用的stream量控制,这是我在任何真正的负载平衡情况下所做的。 这是LRU模式的概括。 见http://hintjens.com/blog:15