Sistema de Mensajeria de Colas con ZeroMQ y PythonErnesto CrespoTwitter: @_seraph1Email: ecrespo@gmail.comBlog: http://ern...
Agenda●   ¿Qué es ZeroMQ?●   Implementar una capa de mensajes con ZeroMQ●   Tipos de transporte●   Patrones de mensajes●  ...
¿Qué es ZeroMQ?Es una librería asíncrona de alto rendimiento de mensajeríadestinado a su uso en aplicaciones distribuidas ...
Implementar una capa de mensajes con ZeroMQPara implementar una capa de mensajes ZeroMQ se necesitan 3 pasos:1. Selecciona...
Tipos de transporteZeroMQ soporta varios estilos de capa de transporte:●   tcp://equipo:puerto, procesos en una red TCP.● ...
Patrones de mensajesLos patrones básicos de ZeroMQ son:● Request/Reply: bidireccional, balanceo de carga y basado en estad...
Seleccionar infraestructuraLuego de definir el tipo de transporte es necesario pensar como losdiferentes componentes se co...
Patrón REQ/REPComunicación bidireccional que facilita el balanceo de carga y sebasa en estados.Este patrón es muy común y ...
Servidor REQ/REP#!/usr/bin/env python#Se importa zeromqimport zmq#Se crea la instancia del contexto de zmq.context = zmq.C...
Cliente REQ/REP#!/usr/bin/env python#Se importa zeromq y randomimport zmqimport random#Se crea la instancia del contextoco...
Patrón PUB/SUBEn este patrón los componentes son pobremente acoplados, son degran ayuda para escalar ya que no existe nece...
Servidor Patrón PUB/SUB#!/usr/bin/env python#Se importa ZeroMQimport zmq#Se importa choice a partir de randomfrom random i...
Servidor Patrón PUB/SUB#Se crea un contador con valor inicial 1c=1#Se crea un ciclo indefinidowhile True:  #Se define un m...
#!/usr/bin/env python                               Cliente 1 Patrón PUB/SUB#Se importa zeroMQimport zmq#Se importa sleep ...
#!/usr/bin/env python                                Cliente 2 Patrón PUB/SUB#Se importa zeroMQimport zmq#Se importa sleep...
Emisor, ejemplo Patrón PUSH/PULL#!/usr/bin/python#Se importa zeroMQ y randomimport zmqimport random#Se crea la instancia d...
Workers, ejemplo Patrón PUSH/PULL#!/usr/bin/python#Se importa ZeroMQ y sleep de timeimport zmqfrom time import sleep#Se cr...
Resultado, ejemplo Patrón PUSH/PULL#!/usr/bin/python#Se importa ZeroMQimport zmq#Se crea la instancia del contextocontext ...
Patrón PairComunicación exlusiva entre pares.Lo que se logra es que si otro nodo intenta conectarse no lo logrará sino est...
Servidor Patrón Pair#!/usr/bin/env python#Importar zmqimport zmq#Se crea la instancia del contextocontext = zmq.Context()#...
Cliente Patrón Pair#!/usr/bin/env python#Se importa zmqimport zmq#Se crea la instancia del contextocontext = zmq.Context()...
Patrones REQ/REP y PUB/SUB Emisor#!/usr/bin/python#Se importa zeroMQimport zmq#Se crea el contextocontext = zmq.Context()#...
Patrones REQ/REP y PUB/SUB Tuiter#!/usr/bin/env python#Se importa zeroMQimport zmq#Se importa choice de randomfrom random ...
Patrones REQ/REP y PUB/SUB Receptor 1:#!/usr/bin/python#Se importa zeroMQimport zmq#Se crea el contextocontext = zmq.Conte...
Patrones REQ/REP y PUB/SUB Receptor 2:#!/usr/bin/python#Se importa zeroMQimport zmq#Se crea el contextocontext = zmq.Conte...
Multicast Productor:#!/usr/bin/env python## producer#Se importa ZeroMQimport zmq#Se crea la instancia de la clase Context....
Multicast Consumidor:#!/usr/bin/env python#Importar zeroMQimport zmq#Se crea la instancia de la clase contextocontext = zm...
Benchmarkhttp://mikehadlow.blogspot.com/2011/04/message-queue-shootout.html
LicenciaEste documento está licenciado bajo la GNU Free DocumentationLicense (GFDL). www.gnu.orgSe autoriza la copia y dis...
Referencias:●   http://nichol.as/zeromq-an-introduction●   http://blog.pythonisito.com/2012/08/distributed-systems-with-ze...
Upcoming SlideShare
Loading in …5
×

Sistema de Mensajeria de Colas con ZeroMQ y Python

3,565 views

Published on

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,565
On SlideShare
0
From Embeds
0
Number of Embeds
1,295
Actions
Shares
0
Downloads
42
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Sistema de Mensajeria de Colas con ZeroMQ y Python

  1. 1. Sistema de Mensajeria de Colas con ZeroMQ y PythonErnesto CrespoTwitter: @_seraph1Email: ecrespo@gmail.comBlog: http://ernesto-ecrespo.blogspot.com
  2. 2. Agenda● ¿Qué es ZeroMQ?● Implementar una capa de mensajes con ZeroMQ● Tipos de transporte● Patrones de mensajes● Seleccionar infraestructura● Patrones de comunicación: ● Patrón Solicitud/Respuesta (Request/Reply) ● Patrón Suscriptor/Publicador(PUB/SUB) ● Patrón PUSH/PULL ● Patrón de mensaje PAR● Otros ejemplos: ● REQ/REP y PUB/SUB ● Multicast● Benchmarks● Licencia● Referencias
  3. 3. ¿Qué es ZeroMQ?Es una librería asíncrona de alto rendimiento de mensajeríadestinado a su uso en aplicaciones distribuidas escalableso concurrentes.Es una librería que soporte distintos patrones de comunicación de redes.ZeroMQ usa colas internamente para el buffer de mensajes para noBloquear aplicaciones al enviar mensajes.Rápido: 8M msg/seg ,30useg de latencia.Licencia: LGPLMultiplataforma y multilenguajes(más de 30 lenguajes de programación)
  4. 4. Implementar una capa de mensajes con ZeroMQPara implementar una capa de mensajes ZeroMQ se necesitan 3 pasos:1. Seleccionar transporte (ipc,tcp,epgm,inproc y pgm).2. Seleccionar infraestructura.3. Seleccionar patrón de mensaje.
  5. 5. Tipos de transporteZeroMQ soporta varios estilos de capa de transporte:● tcp://equipo:puerto, procesos en una red TCP.● inproc://equipo, hilos en un proceso.● ipc:///tmp/archivo socket Unix que permite una comunicación entre procesos.● pgm://interface:dirección:puerto y epgm://interface:dirección:puerto soporta la librería OpenPGM para comunicación multicast sobre IP (pgm) y sobre UDP (epgm).
  6. 6. Patrones de mensajesLos patrones básicos de ZeroMQ son:● Request/Reply: bidireccional, balanceo de carga y basado en estado.● Publish/Subscribe: publica multiples recipientes en uno.● Push/Pull (pipeline): distribuye datos a nodos en un pipeline.● Pair: comunicación exclusiva entre pares.
  7. 7. Seleccionar infraestructuraLuego de definir el tipo de transporte es necesario pensar como losdiferentes componentes se conectan.Tipos de dispositivos:1. Queue: un forwarder para el patrón req/resp.2. Forwarder: un forwarder para el patrón PUB/SUB.3. Streamer: un forwarder para el patrón pipelined.
  8. 8. Patrón REQ/REPComunicación bidireccional que facilita el balanceo de carga y sebasa en estados.Este patrón es muy común y es normalmente usado por varios servicioscomo: HTTP, POP o IMAP.
  9. 9. Servidor REQ/REP#!/usr/bin/env python#Se importa zeromqimport zmq#Se crea la instancia del contexto de zmq.context = zmq.Context()#Se define el socket con parámetro respuesta REP.socket = context.socket(zmq.REP)#Se asocia la dirección IP y el puerto donde el servidor escucha las peticiones.socket.bind("tcp://127.0.0.1:5000")#Se define un contadosc=1#Se genera un ciclo que sólo finaliza si se recibe la letra q.while True: #Se recibe los mensajes. msg = socket.recv() #Se consulta si la longitud del mensaje es 1 y es la letra q se termina el ciclo if len(msg) == 1 and msg == "q": break #Se separa los datos que viene en un string separados por : datos = msg.split(":") #se realiza una suma con los datos recibidos. resultado = int(datos[0]) + int(datos[1]) #Se muestra en pantalla el resultado print "Iteracion: %s ,He recibido: %s, el resultado es: %s " %(c,msg,resultado) #Se envía el resultado al cliente socket.send(str(resultado)) #Se incrementa el contador. c += 1
  10. 10. Cliente REQ/REP#!/usr/bin/env python#Se importa zeromq y randomimport zmqimport random#Se crea la instancia del contextocontext = zmq.Context()#Se crea el socket y se para el argumento de petición REQsocket = context.socket(zmq.REQ)#Se coencta a la IP y puerto donde escucha el servidorsocket.connect("tcp://127.0.0.1:5000")#Se genera un ciclo de 1000 repeticionesfor i in range(1000): #Se crea el string con el mensaje, se pasa 2 aargumentos aleatorios msg = "%s:%s" %(random.randint(1, 1000),random.randint(1, 1000)) #Se envia el mensaje al servidor socket.send(msg) #Se recibe el mensaje del servidor msg_in = socket.recv() #Se muestra en patalla los datos y el resultado print "Iteracion: %s, Enviado: %s, Recibido: %s" %(i,msg,msg_in) #Si se llea a la iteración 999 se envía la letra q para finalizar if i == 999: socket.send("q")
  11. 11. Patrón PUB/SUBEn este patrón los componentes son pobremente acoplados, son degran ayuda para escalar ya que no existe necesidad de preocuparsede los suscriptores.Se puede pensar en servicios como XMPP o twitter, donde los mensajessólo le llegan a las personas que les toca recibirlos.
  12. 12. Servidor Patrón PUB/SUB#!/usr/bin/env python#Se importa ZeroMQimport zmq#Se importa choice a partir de randomfrom random import choice#Se crea la instancia del contextocontext = zmq.Context()#Se crea el socket pasandole argumento de publicacion PUBsocket = context.socket(zmq.PUB)#Se asocia la IP y el puerto que va a escuchar.socket.bind("tcp://127.0.0.1:5000")#Se importa sleepfrom time import sleep#Se crea una lista de paises y de eventospaises = [holanda,brasil,alemania,portugal,argentina,italia,rusia,venezuela]eventos = [tarjeta amarilla,tarjeta roja,gol,corner,falta]
  13. 13. Servidor Patrón PUB/SUB#Se crea un contador con valor inicial 1c=1#Se crea un ciclo indefinidowhile True: #Se define un mensaje pasando de forma aleatoria un pais y un evento mensaje = choice( paises) + " " + choice(eventos) #Se muestra en pantalla el valor del contador y el mensaje. print "->",c , mensaje #Se envia el mensaje socket.send(mensaje) #Se genera un retardo de 1 seg sleep(1) #Se incrementa el contador c += 1 #Si se llega a 180 se termina el ciclo si no continua. if c == 180: break else: continue
  14. 14. #!/usr/bin/env python Cliente 1 Patrón PUB/SUB#Se importa zeroMQimport zmq#Se importa sleep a partir de timefrom time import sleep#Se crea la instancia del contexto de zeroMQcontext = zmq.Context()#Se crea el socket del suscriptor SUBsocket = context.socket(zmq.SUB)#Se crea la conexion a la IP y puerto del servidorsocket.connect("tcp://127.0.0.1:5000")#Se define una opcion del socket del suscriptor con argentina y venezuelasocket.setsockopt(zmq.SUBSCRIBE, "argentina")socket.setsockopt(zmq.SUBSCRIBE, "venezuela")#Se define el valor inicial de un contadorc=1#Se crea un ciclo indefinidowhile True: #Se muestra en pantalla el valor del contador y el mensaje recibido print c, "->",socket.recv() #Se genera un retardo de 1 seg en cada ciclo sleep(1) #Se incrementa el contador en 1 c += 1 #Si el contador llega a 90 se termina el ciclo, si no continua if c == 90: break else: continue
  15. 15. #!/usr/bin/env python Cliente 2 Patrón PUB/SUB#Se importa zeroMQimport zmq#Se importa sleep a partir de timefrom time import sleep#Se crea la instancia del contexto de zeroMQcontext = zmq.Context()#Se crea el socket del suscriptor SUBsocket = context.socket(zmq.SUB)#Se crea la conexion a la IP y puerto del servidorsocket.connect("tcp://127.0.0.1:5000")#Se define una opcion del socket del suscriptor con brasil y alemaniasocket.setsockopt(zmq.SUBSCRIBE, "brasil")socket.setsockopt(zmq.SUBSCRIBE, "alemania")#Se define el valor inicial de un contadorc=1#Se crea un ciclo indefinidowhile True: #Se muestra en pantalla el valor del contador y el mensaje recibido print c, "->",socket.recv() #Se genera un retardo de 1 seg en cada ciclo sleep(1) #Se incrementa el contador en 1 c += 1 #Si el contador llega a 90 se termina el ciclo, si no continua if c == 90: break else: continue
  16. 16. Emisor, ejemplo Patrón PUSH/PULL#!/usr/bin/python#Se importa zeroMQ y randomimport zmqimport random#Se crea la instancia del contextocontext = zmq.Context()#Se crea el socket con el argumento PUSHenvio =context.socket(zmq.PUSH)#Se asocia el socket a escuchar todas las IPs y el puerto 5557envio.bind("tcp://*:5557")#se muestra que es necesario esperar que arranquen los workersprint "Hay que esperar que los workers se inicien"#Al dar enter se inicia el proceso de transmisionraw_input()print "Se inicia la transmision del trabajo..."#tupla de strings que se van a enviarcadenas = [hola, aloha,hello,buenas noches,buenas tardes,buenos dias,bienvenido]#Se crea un ciclo para recorrer la tuplafor i in range(len(cadenas)): cadena = cadenas[i] envio.send(cadena) print "Enviando: {0}".format(cadena)
  17. 17. Workers, ejemplo Patrón PUSH/PULL#!/usr/bin/python#Se importa ZeroMQ y sleep de timeimport zmqfrom time import sleep#Se crea la instancia del contextocontext = zmq.Context()#Se define el Socket con argumento PULLrecepcion = context.socket(zmq.PULL)#Se conecta el socket a localhost puerto 5557#Es el puerto donde origen envia con PUSH los datosrecepcion.connect("tcp://localhost:5557")#Se crea el socket de envio de los datos procesados con argumento PUSHenvio = context.socket(zmq.PUSH)#Se conecta el socket a localhost y puerto 5558envio.connect("tcp://localhost:5558")#Se genera un ciclo#donde se recive lo transmitido por origen#se procesa (se coloca en mayusculas)#se muestra en pantalla y se envia.#los ciclos tienen un retardo de 1 segwhile True: cadena = recepcion.recv() print "Proceso:{0}".format(cadena) envio.send(cadena.upper()) sleep(1)
  18. 18. Resultado, ejemplo Patrón PUSH/PULL#!/usr/bin/python#Se importa ZeroMQimport zmq#Se crea la instancia del contextocontext = zmq.Context()#Se crea el socket PULL que recibe los mensajes de los workersrecepcion = context.socket(zmq.PULL)#Se asocia el socket a escuchar todas las IPs en el puerto 5558#el puerto donde los workers envian los mensajesrecepcion.bind("tcp://*:5558")#Se inicia un ciclo donde se recibe los mensajes#de los workers y se muestra en pantallawhile True: mensaje = recepcion.recv() print "Recibo: {0}".format(mensaje)
  19. 19. Patrón PairComunicación exlusiva entre pares.Lo que se logra es que si otro nodo intenta conectarse no lo logrará sino está declarado.Si está declarado, este establece conexión pero saca al nodo anterior.
  20. 20. Servidor Patrón Pair#!/usr/bin/env python#Importar zmqimport zmq#Se crea la instancia del contextocontext = zmq.Context()#Se crea el socket del tipo PARsocket = context.socket(zmq.PAIR)#Se asocia a una IP y puerto donde escucha el servidor.socket.bind("tcp://127.0.0.1:5555")#Se crea un ciclo.while True: #Se recibe un mensaje del cliente mensaje = socket.recv() #Se muestra en pantalla print "Recivo", mensaje #Se envia de vuelta el mensaje socket.send(mensaje)
  21. 21. Cliente Patrón Pair#!/usr/bin/env python#Se importa zmqimport zmq#Se crea la instancia del contextocontext = zmq.Context()#Se crea el socket con argumento del tipo de mensaje Par.socket = context.socket(zmq.PAIR)#Se conecta al servidor dado la IP y puerto.socket.connect("tcp://127.0.0.1:5555")#Se crea un cilo de 100 repeticiones.for i in range(100): #Se define el mensaje a pasar mensaje = "mensaje %s" % i #Se pasa el mensaje al servidor socket.send(mensaje) #Se presenta en pantalla el mensaje print "Enviando", mensaje #Se recibe el mensaje de vuelta msg_in = socket.recv() #Se presenta en pantalla el mensaje de vuelta print "Recibido:", msg_in
  22. 22. Patrones REQ/REP y PUB/SUB Emisor#!/usr/bin/python#Se importa zeroMQimport zmq#Se crea el contextocontext = zmq.Context()#Se crea el socket con el parametro REQsocket = context.socket(zmq.REQ)#Se asocia la IP y el puerto del socket.socket.connect("tcp://127.0.0.1:4000")#Se genera los mensajes estilo tuiter y se envia al socket.for i in [@_seraph1 Esta es una prueba,@otro viendo el juego, @_seraph1 otra prueba,@otro otro]: socket.send(i) msg_in = socket.recv()
  23. 23. Patrones REQ/REP y PUB/SUB Tuiter#!/usr/bin/env python#Se importa zeroMQimport zmq#Se importa choice de randomfrom random import choice#Se crea el contextocontext = zmq.Context()#Se define el socket de recepcion con argumento REPsocket_recv = context.socket(zmq.REP)#Se asocia a una IP y puerto el socket de recepcionsocket_recv.bind("tcp://127.0.0.1:4000")#Se define el socket de publicacion con argumento PUBsocket = context.socket(zmq.PUB)#Se asocia la ip y un puerto distinto al anterio socketsocket.bind("tcp://127.0.0.1:5000")#Se crea un ciclowhile True: #Se recibe el mensaje del socket de recepcion msg = socket_recv.recv() #Se envia el mensaje de recepcion socket_recv.send(msg) #Se muestra el mensaje en pantalla print "Reenvio: {0}".format(msg) #Se envia el mensaje al socket de publicacion socket.send(msg)
  24. 24. Patrones REQ/REP y PUB/SUB Receptor 1:#!/usr/bin/python#Se importa zeroMQimport zmq#Se crea el contextocontext = zmq.Context()#Se crea el socket de suscripcionsocket = context.socket(zmq.SUB)#Se asocia ese socket a la IP y puerto donde publica tuitersocket.connect("tcp://127.0.0.1:5000")#Se suscribe a escuchar los mensajes de @_seraph1socket.setsockopt(zmq.SUBSCRIBE, "@_seraph1")#se crea un ciclo donde se recibe los mensajeswhile True: print "->",socket.recv()
  25. 25. Patrones REQ/REP y PUB/SUB Receptor 2:#!/usr/bin/python#Se importa zeroMQimport zmq#Se crea el contextocontext = zmq.Context()#Se crea el socket de suscripcionsocket = context.socket(zmq.SUB)#Se asocia ese socket a la IP y puerto donde publica tuitersocket.connect("tcp://127.0.0.1:5000")#Se suscribe a escuchar los mensajes de @otrosocket.setsockopt(zmq.SUBSCRIBE, "@otro")#se crea un ciclo donde se recibe los mensajeswhile True: print "->",socket.recv()
  26. 26. Multicast Productor:#!/usr/bin/env python## producer#Se importa ZeroMQimport zmq#Se crea la instancia de la clase Context.context = zmq.Context()#Se define el socket con parametro PUBsocket = context.socket(zmq.PUB)#Se define unas opciones en el socket#esta opcion LINGER con valor cero, descarta mensajes no enviadossocket.setsockopt(zmq.LINGER, 0)#Se conecta al socket a la IP y puerto#por medio de multicastsocket.connect(epgm://192.168.10.96:5000)#Se crea un ciclo#si se envia el texto salir, se envia y luego finaliza el ciclo#si no, se envia el textowhile True: mensaje = raw_input("->") print mensaje socket.send(mensaje) if mensaje == "salir": breaksocket.close()
  27. 27. Multicast Consumidor:#!/usr/bin/env python#Importar zeroMQimport zmq#Se crea la instancia de la clase contextocontext = zmq.Context()#Se define el socket con parametro SUBsocket = context.socket(zmq.SUB)#Se conecta el socket a la IP y puerto del productor#con el transporte epgmsocket.connect(epgm://192.168.10.96:5000)#Se define los textos que se recibe la informacion.#prueba, hora y salir.socket.setsockopt(zmq.SUBSCRIBE, prueba)socket.setsockopt(zmq.SUBSCRIBE, hora)socket.setsockopt(zmq.SUBSCRIBE, salir)#Se define un ciclo,#se recibe la informacion#Si el texto es salir se muestra en pantalla#finaliza el ciclo, si no se muestra#el texto en pantallawhile True: rcv = socket.recv() print rcv if rcv == "salir": beak
  28. 28. Benchmarkhttp://mikehadlow.blogspot.com/2011/04/message-queue-shootout.html
  29. 29. LicenciaEste documento está licenciado bajo la GNU Free DocumentationLicense (GFDL). www.gnu.orgSe autoriza la copia y distribución por cualquier medio, siempreque se realice bajo esta misma licencia, se mencione al autororiginal y se incluya esta nota.
  30. 30. Referencias:● http://nichol.as/zeromq-an-introduction● http://blog.pythonisito.com/2012/08/distributed-systems-with-zeromq.html● http://mikehadlow.blogspot.com/2011/04/message-queue-shootout.html● http://pop-servis.blogspot.com/2011/04/benchmarking-zeromq-over-network.html● http://ernesto-ecrespo.blogspot.com/search/label/ZeroMQ● http://www.zeromq.org/results:multicore-tests● http://www.zeromq.org/results:10gbe-tests-v031● http://blog.pythonisito.com/2012/08/zeromq-flow-control-and-other-options.html#more

×