En expérimentant le ZeroMQ
Push/Pull
(ce qu'ils appellent Pipeline
), j'ai du mal à comprendre l'utilité de ce modèle. Il est présenté comme un "équilibreur de charge".
Dans le cas d'un serveur unique envoyant des tâches à un certain nombre de travailleurs, Push/Pull répartira les tâches de manière égale entre tous les clients. 3 clients et 30 tâches, chaque client reçoit 10 tâches : client1 reçoit les tâches 1, 4, 7,... client2, 2, 5,... et ainsi de suite. C'est équitable. Littéralement.
Cependant, dans la pratique, il y a souvent un mélange non homogène de la complexité des tâches ou des ressources informatiques du client (ou de leur disponibilité), alors ce modèle se casse la figure. Toutes les tâches semblent être programmées à l'avance, et le serveur n'a aucune connaissance de la progression des clients ou même de leur disponibilité. Si le client 1 tombe en panne, ses tâches restantes ne sont pas envoyées aux autres clients, mais restent en file d'attente pour le client 1. Si le client1 reste en panne, ces tâches ne sont jamais traitées. Inversement, si un client est plus rapide dans le traitement de ses tâches, il ne reçoit pas d'autres tâches et reste inactif, car elles restent programmées pour les autres clients.
Utilisation de REQ/REP
est une solution possible ; les tâches ne sont alors confiées qu'à une ressource disponible .
Alors j'ai raté quelque chose ? Comment est-ce que Push/Pull
pour être utilisé efficacement ? Existe-t-il un moyen de gérer l'asymétrie des clients, des tâches, etc., avec ce type de socket ?
Merci !
Voici un exemple simple en 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)
Lancez 3 clients avec un paramètre de délai sur la ligne de commande (par exemple, 1, 1, et 0.1) et ensuite le serveur, et voyez comment toutes les tâches sont distribuées de manière égale. Ensuite, tuez l'un des clients pour voir si ses tâches restantes ne sont pas traitées.
Décommentez les lignes indiquées pour le changer en un Req/Rep
et regarder un équilibreur de charge plus efficace.