Je viens de commencer avec ZMQ. Je conçois une application dont le workflow est:
Je suppose que l'architecture Push/PULL est adaptée à cela. S'il vous plaît corrigez-moi à ce sujet.
Mais comment gérer ces scénarios?
Alors, comment puis-je configurer quelque chose comme un timeout dans le modèle Push/PULL?
MODIFIER : Merci aux suggestions de user938949, j'ai reçu réponse de travail et je le partage pour la postérité.
Si vous utilisez zeromq> = 3.0, vous pouvez définir l'option de socket RCVTIMEO:
client_receiver.RCVTIMEO = 1000 # in milliseconds
Mais en général, vous pouvez utiliser des sondeurs:
poller = zmq.Poller()
poller.register(client_receiver, zmq.POLLIN) # POLLIN for recv, POLLOUT for send
Et poller.poll()
prend un timeout:
evts = poller.poll(1000) # wait *up to* one second for a message to arrive.
evts
sera une liste vide s'il n'y a rien à recevoir.
Vous pouvez interroger avec zmq.POLLOUT
, Pour vérifier si un envoi réussira.
Ou, pour gérer le cas d'un homologue qui aurait pu échouer, a:
worker.send(msg, zmq.NOBLOCK)
peut suffire, qui reviendra toujours immédiatement - en lançant une ZMQError (zmq.EAGAIN) si l'envoi ne peut pas se terminer.
Ce fut un hack rapide que j'ai fait après avoir référé la réponse de user938949 et http://taotetek.wordpress.com/2011/02/02/02/python-multiprocessing-with-zeromq / . Si vous faites mieux, veuillez poster votre réponse, Je recommanderai votre réponse .
Pour ceux qui souhaitent des solutions durables sur la fiabilité, reportez-vous http://zguide.zeromq.org/page:all#toc64
La version 3.0 de zeromq (beta ATM) prend en charge timeout dans ZMQ_RCVTIMEO et ZMQ_SNDTIMEO. http://api.zeromq.org/3-0:zmq-setsockopt
Le zmq.NOBLOCK garantit que lorsqu'un client n'existe pas, send () ne se bloque pas.
import time
import zmq
context = zmq.Context()
ventilator_send = context.socket(zmq.Push)
ventilator_send.bind("tcp://127.0.0.1:5557")
i=0
while True:
i=i+1
time.sleep(0.5)
print ">>sending message ",i
try:
ventilator_send.send(repr(i),zmq.NOBLOCK)
print " succeed"
except:
print " failed"
L'objet poller peut écouter sur de nombreuses sockets de réception (voir le "Multiprocessing Python avec ZeroMQ" lié ci-dessus. Je l'ai lié uniquement sur work_receiver . Dans l'infini , le client interroge avec un intervalle de 1000 ms. L'objet socks retourne vide si aucun message n'a été reçu pendant cette période.
import time
import zmq
context = zmq.Context()
work_receiver = context.socket(zmq.PULL)
work_receiver.connect("tcp://127.0.0.1:5557")
poller = zmq.Poller()
poller.register(work_receiver, zmq.POLLIN)
# Loop and accept messages from both channels, acting accordingly
while True:
socks = dict(poller.poll(1000))
if socks:
if socks.get(work_receiver) == zmq.POLLIN:
print "got message ",work_receiver.recv(zmq.NOBLOCK)
else:
print "error: message timeout"
L'envoi ne bloquera pas si vous utilisez ZMQ_NOBLOCK, mais si vous essayez de fermer le socket et le contexte, cette étape empêcherait le programme de quitter.
La raison en est que le socket attend tout homologue afin que les messages sortants soient mis en file d'attente. Pour fermer immédiatement le socket et vider les messages sortants du tampon, utilisez ZMQ_LINGER et réglez-le sur 0.
Si vous n'attendez qu'une seule socket, plutôt que de créer un Poller
, vous pouvez le faire:
if work_receiver.poll(1000, zmq.POLLIN):
print "got message ",work_receiver.recv(zmq.NOBLOCK)
else:
print "error: message timeout"
Vous pouvez l'utiliser si votre délai d'attente change en fonction de la situation, au lieu de définir work_receiver.RCVTIMEO
.