sub - Utilidad del patrón ZeroMQ Push/Pull
zmq req (1)
No es un balanceador de carga, esta fue una explicación errónea que permaneció en los documentos de 0MQ por un tiempo. Para equilibrar la carga, debe obtener información de parte de los trabajadores sobre su disponibilidad. PUSH, como DEALER, es un distribuidor de turnos. Es útil por su velocidad bruta y su simplicidad. No necesita ningún tipo de charla, solo transfiera las tareas a la tubería y se pulverizan a todos los trabajadores disponibles tan rápido como la red pueda manejarlos.
El patrón es útil cuando está haciendo un gran número de tareas pequeñas, y donde los trabajadores entran y salen con poca frecuencia. El patrón no es bueno para las tareas más grandes que tardan en completarse porque entonces desea una sola cola que envíe nuevas tareas solo a los trabajadores disponibles. También sufre de un antipatrón en el que si un cliente envía muchas tareas y luego los trabajadores se conectan, el primer trabajador tomará aproximadamente 1,000 mensajes mientras los demás aún están ocupados conectando.
Puede hacer su propio enrutamiento de alto nivel de varias maneras. Mire los patrones de LRU en la Guía: en esto los trabajadores explícitamente le dicen al agente "listo". También puede hacer un control de flujo basado en crédito, y esto es lo que haría en cualquier situación de equilibrio de carga real. Es una generalización del patrón LRU. Ver http://hintjens.com/blog:15
Al experimentar con el tipo de socket ZeroMQ
Push/Pull
(lo que ellos llaman Pipeline
), estoy teniendo dificultades para entender la utilidad de este patrón. Se factura como un "equilibrador de carga".
Dado que un servidor único envía tareas a un número de trabajadores, Push / Pull repartirá las tareas entre todos los clientes. 3 clientes y 30 tareas, cada cliente obtiene 10 tareas: client1 obtiene tareas 1, 4, 7, ... client2, 2, 5, ... y así sucesivamente. Lo suficientemente justo. Literalmente.
Sin embargo, en la práctica, a menudo existe una mezcla no homogénea de complejidad de tareas o recursos de computación del cliente (o disponibilidad), entonces este patrón se rompe mal. Todas las tareas parecen estar programadas de antemano, y el servidor no tiene conocimiento del progreso de los clientes o si están disponibles. Si el cliente1 se cae, sus tareas restantes no se envían a los demás clientes, sino que permanecen en cola para el cliente1. Si el cliente1 permanece inactivo, entonces esas tareas nunca se manejan. Por el contrario, si un cliente es más rápido en el procesamiento de sus tareas, no obtiene más tareas y permanece inactivo, ya que siguen programadas para los otros clientes.
Usar REQ/REP
es una posible solución; las tareas solo se dan a un recurso disponible.
Entonces, ¿me estoy perdiendo algo? ¿Cómo se usa Push/Pull
de manera efectiva? ¿Hay alguna forma de manejar la asimetría de clientes, tareas, etc. con este tipo de socket?
¡Gracias!
Aquí hay un ejemplo simple de 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)
Arranque 3 clientes con un parámetro de retardo en la línea de comando (es decir, 1, 1 y 0.1) y luego el servidor, y vea cómo todas las tareas están distribuidas uniformemente. Luego mata a uno de los clientes para ver que no se manejan las tareas restantes.
Descomente las líneas indicadas para cambiarlo a un socket de tipo Req/Rep
y ver un equilibrador de carga más efectivo.