114
Monday, July 4, 2011

Desacoplando aplicaciones

Embed Size (px)

DESCRIPTION

Charla dada durante las Jornadas Symfony en Castellón, España. Julio 2011

Citation preview

Page 1: Desacoplando aplicaciones

Monday, July 4, 2011

Page 2: Desacoplando aplicaciones

Monday, July 4, 2011

Page 3: Desacoplando aplicaciones

About Me

• Desarrollador en Liip AG

• Blog: http://videlalvaro.github.com/

• Twitter: @old_sound

Monday, July 4, 2011

Page 4: Desacoplando aplicaciones

About Me

Escribiendo

RabbitMQ in Action

http://bit.ly/rabbitmq

Monday, July 4, 2011

Page 5: Desacoplando aplicaciones

¿Por qué necesito usar Mensajería?

Monday, July 4, 2011

Page 6: Desacoplando aplicaciones

Veamos un ejemplo

Monday, July 4, 2011

Page 7: Desacoplando aplicaciones

Implementar una Galería de Imágenes

Monday, July 4, 2011

Page 8: Desacoplando aplicaciones

Dos Partes:

Monday, July 4, 2011

Page 9: Desacoplando aplicaciones

¿Bastante fácil no?

Monday, July 4, 2011

Page 10: Desacoplando aplicaciones

Hasta que nuevos requerimientos

comienzan a llegar

Monday, July 4, 2011

Page 11: Desacoplando aplicaciones

El Propietario del Producto

Monday, July 4, 2011

Page 12: Desacoplando aplicaciones

¿Podemos notificar a los amigos del usuario

sobre nuevas imágenes?

Monday, July 4, 2011

Page 13: Desacoplando aplicaciones

¿Podemos notificar a los amigos del usuario

sobre nuevas imágenes?

Me olvidé de decirles que lo necesito para mañana

Monday, July 4, 2011

Page 14: Desacoplando aplicaciones

El “Social Media Guru”

Monday, July 4, 2011

Page 15: Desacoplando aplicaciones

Necesitamos premiar a los usuarios por cada

foto que suben

Monday, July 4, 2011

Page 16: Desacoplando aplicaciones

Necesitamos premiar a los usuarios por cada

foto que suben

y enviar notificaciones a Twitter

Monday, July 4, 2011

Page 17: Desacoplando aplicaciones

El Administrador de Sistemas

Monday, July 4, 2011

Page 18: Desacoplando aplicaciones

¡Dolobu! Estamos sirviendo imágenes sin achicar. ¡La cuenta de

ancho de banda a triplicado!

Monday, July 4, 2011

Page 19: Desacoplando aplicaciones

¡Necesitamos arreglar esto para mañana!

¡Dolobu! Estamos sirviendo imágenes sin achicar. ¡La cuenta de

ancho de banda a triplicado!

Monday, July 4, 2011

Page 20: Desacoplando aplicaciones

El Desarrollador en el otro equipo

Monday, July 4, 2011

Page 21: Desacoplando aplicaciones

Necesito llamar tus sistemas PHP pero

desde Python

Monday, July 4, 2011

Page 22: Desacoplando aplicaciones

Necesito llamar tus sistemas PHP pero

desde Python

Y la semana que viene Java también

Monday, July 4, 2011

Page 23: Desacoplando aplicaciones

El Usuario

Monday, July 4, 2011

Page 24: Desacoplando aplicaciones

No quiero tener que esperar que tu

aplicación procese la imagen

Monday, July 4, 2011

Page 25: Desacoplando aplicaciones

Tu

Monday, July 4, 2011

Page 26: Desacoplando aplicaciones

FML!

Monday, July 4, 2011

Page 27: Desacoplando aplicaciones

Veamos la evolución del código

Monday, July 4, 2011

Page 28: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> image_handler:do_upload(ReqData:get_file()), ok.

Primera implementación:

Monday, July 4, 2011

Page 29: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()), resize_image(Image),ok.

Segunda implementación:

Monday, July 4, 2011

Page 30: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()), resize_image(Image),notify_friends(ReqData:get_user()),ok.

Tercera implementación:

Monday, July 4, 2011

Page 31: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()), resize_image(Image),notify_friends(ReqData:get_user()),add_points_to_user(ReqData:get_user()),ok.

Cuarta implementación:

Monday, July 4, 2011

Page 32: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()), resize_image(Image),notify_friends(ReqData:get_user()),add_points_to_user(ReqData:get_user()),tweet_new_image(User, Image),ok.

Implementación final:

Monday, July 4, 2011

Page 33: Desacoplando aplicaciones

¿Escala nuestro código a nuevos

requerimientos?

Monday, July 4, 2011

Page 34: Desacoplando aplicaciones

Qué pasaría si…

Monday, July 4, 2011

Page 35: Desacoplando aplicaciones

Qué pasaría si…

• Necesitamos acelerar la conversión de imágenes

Monday, July 4, 2011

Page 36: Desacoplando aplicaciones

Qué pasaría si…

• Necesitamos acelerar la conversión de imágenes

• Las notificaciones a los usuarios tienen que ser enviadas por email

Monday, July 4, 2011

Page 37: Desacoplando aplicaciones

Qué pasaría si…

• Necesitamos acelerar la conversión de imágenes

• Las notificaciones a los usuarios tienen que ser enviadas por email

• Tenemos que dejar de twittear sobre nuevas imágenes

Monday, July 4, 2011

Page 38: Desacoplando aplicaciones

Qué pasaría si…

• Necesitamos acelerar la conversión de imágenes

• Las notificaciones a los usuarios tienen que ser enviadas por email

• Tenemos que dejar de twittear sobre nuevas imágenes

• Convertir imágenes a diferentes formatos

Monday, July 4, 2011

Page 39: Desacoplando aplicaciones

¿Podemos hacerlo mejor?

Monday, July 4, 2011

Page 40: Desacoplando aplicaciones

Por supuesto.Usando Mensajería.

Monday, July 4, 2011

Page 41: Desacoplando aplicaciones

DiseñoPublish / Subscribe Pattern

Monday, July 4, 2011

Page 42: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()),Msg = #msg{user = ReqData:get_user(), image = Image},publish_message('new_image', Msg).

Primera Implementación:

Monday, July 4, 2011

Page 43: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()),Msg = #msg{user = ReqData:get_user(), image = Image},publish_message('new_image', Msg).

Primera Implementación:

%% friends notifieron('new_image', Msg) ->notify_friends(Msg.user, Msg.image).

Monday, July 4, 2011

Page 44: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()),Msg = #msg{user = ReqData:get_user(), image = Image},publish_message('new_image', Msg).

Primera Implementación:

%% friends notifieron('new_image', Msg) ->notify_friends(Msg.user, Msg.image).

%% points manageron('new_image', Msg) ->add_points(Msg.user, 'new_image').

Monday, July 4, 2011

Page 45: Desacoplando aplicaciones

%% image_controllerhandle('PUT', "/user/image", ReqData) -> {ok, Image} = image_handler:do_upload(ReqData:get_file()),Msg = #msg{user = ReqData:get_user(), image = Image},publish_message('new_image', Msg).

Primera Implementación:

%% friends notifieron('new_image', Msg) ->notify_friends(Msg.user, Msg.image).

%% points manageron('new_image', Msg) ->add_points(Msg.user, 'new_image').

%% resizeron('new_image', Msg) ->resize_image(Msg.image).

Monday, July 4, 2011

Page 46: Desacoplando aplicaciones

Segunda Implementación:

Monday, July 4, 2011

Page 47: Desacoplando aplicaciones

Segunda Implementación:

THIS PAGE INTENTIONALLY LEFT BLANK

Monday, July 4, 2011

Page 48: Desacoplando aplicaciones

Mensajería

Monday, July 4, 2011

Page 49: Desacoplando aplicaciones

Mensajería

• Compartir datos entre procesos

Monday, July 4, 2011

Page 50: Desacoplando aplicaciones

Mensajería

• Compartir datos entre procesos

• Procesos pueden ser parte de diferentes aplicaciones

Monday, July 4, 2011

Page 51: Desacoplando aplicaciones

Mensajería

• Compartir datos entre procesos

• Procesos pueden ser parte de diferentes aplicaciones

• Aplicaciones pueden vivir en diferentes computadores

Monday, July 4, 2011

Page 52: Desacoplando aplicaciones

Mensajería

• Compartir datos entre procesos

• Procesos pueden ser parte de diferentes aplicaciones

• Aplicaciones pueden vivir en diferentes computadores

• La comunicación es asíncrona

Monday, July 4, 2011

Page 53: Desacoplando aplicaciones

Conceptos Principales

Monday, July 4, 2011

Page 54: Desacoplando aplicaciones

Conceptos Principales

• Mensajes son enviados por Producers

Monday, July 4, 2011

Page 55: Desacoplando aplicaciones

Conceptos Principales

• Mensajes son enviados por Producers

• Mensajes se envían a Consumers

Monday, July 4, 2011

Page 56: Desacoplando aplicaciones

Conceptos Principales

• Mensajes son enviados por Producers

• Mensajes se envían a Consumers

• Mensajes van a través de un Channel

Monday, July 4, 2011

Page 57: Desacoplando aplicaciones

RabbitMQy la

Mensajería

Monday, July 4, 2011

Page 58: Desacoplando aplicaciones

¿Qué es RabbitMQ?

Monday, July 4, 2011

Page 59: Desacoplando aplicaciones

RabbitMQ

• Sistema de Mensajería Empresarial

• Código Libre MPL

• Escrito en Erlang/OTP

• Soporte Comercial

• Mensajería via AMQP

Monday, July 4, 2011

Page 60: Desacoplando aplicaciones

Features

• Confiable y Altamente Escalable

• Fácil de Instalar

• Fácil de Clusterizar

• Corre en: Windows, Solaris, Linux, OSX

• AMQP 0.8 - 0.9.1

Monday, July 4, 2011

Page 61: Desacoplando aplicaciones

Librerías AMQP

• Java

• .NET/C#

• Erlang

• Ruby, Python, PHP, Perl, AS3, Lisp, Scala, Clojure, Haskell

Monday, July 4, 2011

Page 62: Desacoplando aplicaciones

AMQP

• Advanced Message Queuing Protocol

• Pensado para la Interoperabilidad

• Protocolo Completamente Abierto

• Protocol Binario

Monday, July 4, 2011

Page 63: Desacoplando aplicaciones

Flujo de Mensajes

http://www.redhat.com/docs/en-US/Red_Hat_Enterprise_MRG/1.0/html/Messaging_Tutorial/chap-Messaging_Tutorial-Initial_Concepts.html

Monday, July 4, 2011

Page 64: Desacoplando aplicaciones

Modelo AMQP

• Exchanges

• Message Queues

• Bindings

• Rules for binding them

Monday, July 4, 2011

Page 65: Desacoplando aplicaciones

Tipos de Exchange

• Fanout

• Direct

• Topic

Monday, July 4, 2011

Page 69: Desacoplando aplicaciones

Patrones de Mensajería

Monday, July 4, 2011

Page 70: Desacoplando aplicaciones

Les recomiendo un libro al respecto:

http://www.eaipatterns.com/

Monday, July 4, 2011

Page 71: Desacoplando aplicaciones

Patrones Básicos

Monday, July 4, 2011

Page 72: Desacoplando aplicaciones

Competing Consumers

How can a messaging client process multiple

messages concurrently?

Monday, July 4, 2011

Page 73: Desacoplando aplicaciones

Competing Consumers

Create multiple Competing Consumers on a single channel

so that the consumers can process multiple messages

concurrently.

Monday, July 4, 2011

Page 74: Desacoplando aplicaciones

Competing Consumers

Monday, July 4, 2011

Page 75: Desacoplando aplicaciones

Código Publisherinit(Exchange, Queue) -> #'exchange.declare'{exchange = Exchange,

type = <<"direct">>, durable = true},

#'queue.declare'{queue = Queue, durable = false},#'queue.bind'{queue = Queue, exchange = Exchange}.

publish_msg(Exchange, Payload) -> Props = #'P_basic'{content_type = <<"application/json">>,

delivery_mode = 2}, %% persistent publish(Exchange, #amqp_msg{props = Props, payload = Payload}).

Monday, July 4, 2011

Page 76: Desacoplando aplicaciones

Código Consumer

init_consumer(Exchange, Queue) ->init(Exchange, Queue),#'basic.consume'{queue = Queue}.

on(#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{} = Msg) -> do_something_with_msg(Msg), #'basic.ack'{delivery_tag = DeliveryTag}.

Monday, July 4, 2011

Page 77: Desacoplando aplicaciones

Publish/Subscribe

How can the sender broadcast an event to all

interested receivers?

Monday, July 4, 2011

Page 78: Desacoplando aplicaciones

Publish/Subscribe

Send the event on a Publish-Subscribe Channel, which delivers a copy of a

particular event to each receiver.

Monday, July 4, 2011

Page 79: Desacoplando aplicaciones

Publish/Subscribe

Monday, July 4, 2011

Page 80: Desacoplando aplicaciones

Código Pulbisherinit(Exchange, Queue) -> #'exchange.declare'{exchange = Exchange,

type = <<"fanout">>, %% different type durable = true}

%% same as before ...

publish_msg(Exchange, Payload) -> Props = #'P_basic'{content_type = <<"application/json">>,

delivery_mode = 2}, %% persistent publish(Exchange, #amqp_msg{props = Props, payload = Payload}).

Monday, July 4, 2011

Page 81: Desacoplando aplicaciones

Código Consumer A

init_consumer(Exchange, ResizeImageQueue) ->init(Exchange, ResizeImageQueue),#'basic.consume'{queue = ResizeImageQueue}.

on(#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{} = Msg) -> resize_message(Msg), #'basic.ack'{delivery_tag = DeliveryTag}.

Monday, July 4, 2011

Page 82: Desacoplando aplicaciones

Código Consumer B

init_consumer(Exchange, NotifyFriendsQueue) ->init(Exchange, NotifyFriendsQueue),#'basic.consume'{queue = NotifyFriendsQueue}.

on(#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{} = Msg) -> notify_friends(Msg), #'basic.ack'{delivery_tag = DeliveryTag}.

Monday, July 4, 2011

Page 83: Desacoplando aplicaciones

Código Consumer C

init_consumer(Exchange, LogImageUpload) ->init(Exchange, LogImageUpload),#'basic.consume'{queue = LogImageUpload}.

on(#'basic.deliver'{delivery_tag = DeliveryTag}, #amqp_msg{} = Msg) -> log_image_upload(Msg), #'basic.ack'{delivery_tag = DeliveryTag}.

Monday, July 4, 2011

Page 84: Desacoplando aplicaciones

Request/Reply

When an application sends a message, how can it get a response from the

receiver?

Monday, July 4, 2011

Page 85: Desacoplando aplicaciones

Request/Reply

Send a pair of Request-Reply messages, each on its own channel.

Monday, July 4, 2011

Page 86: Desacoplando aplicaciones

Request/Reply

Monday, July 4, 2011

Page 87: Desacoplando aplicaciones

Return Address

How does a replier know where to send the reply?

Monday, July 4, 2011

Page 88: Desacoplando aplicaciones

Return Address

The request message should contain a Return Address that indicates where to send

the reply message.

Monday, July 4, 2011

Page 89: Desacoplando aplicaciones

Return Address

Monday, July 4, 2011

Page 90: Desacoplando aplicaciones

Correlation Identifier

How does a requestor that has received a reply know which request this is the reply for?

Monday, July 4, 2011

Page 91: Desacoplando aplicaciones

Correlation Identifier

Each reply message should contain a Correlation Identifier, a unique identifier that indicates which

request message this reply is for.

Monday, July 4, 2011

Page 92: Desacoplando aplicaciones

Correlation Identifier

Monday, July 4, 2011

Page 93: Desacoplando aplicaciones

Atando Cabos

Monday, July 4, 2011

Page 94: Desacoplando aplicaciones

Cliente RPCinit() -> #'queue.declare_ok'{queue = SelfQueue} = #'queue.declare'{exclusive = true, auto_delete = true},

#'basic.consume'{queue = SelfQueue, no_ack = true}, SelfQueue.

Monday, July 4, 2011

Page 95: Desacoplando aplicaciones

Cliente RPCinit() -> #'queue.declare_ok'{queue = SelfQueue} = #'queue.declare'{exclusive = true, auto_delete = true},

#'basic.consume'{queue = SelfQueue, no_ack = true}, SelfQueue.

request(Payload, RequestId) -> Props = #'P_basic'{correlation_id = RequestId,

reply_to = SelfQueue}, publish(ServerExchange, #amqp_msg{props = Props,

payload = Payload}).

Monday, July 4, 2011

Page 96: Desacoplando aplicaciones

Cliente RPCinit() -> #'queue.declare_ok'{queue = SelfQueue} = #'queue.declare'{exclusive = true, auto_delete = true},

#'basic.consume'{queue = SelfQueue, no_ack = true}, SelfQueue.

request(Payload, RequestId) -> Props = #'P_basic'{correlation_id = RequestId,

reply_to = SelfQueue}, publish(ServerExchange, #amqp_msg{props = Props,

payload = Payload}).

on(#'basic.deliver'{}, #amqp_msg{props = Props, payload = Payload}) ->

CorrelationId = Props.correlation_id, do_something_with_reply(Payload).

Monday, July 4, 2011

Page 97: Desacoplando aplicaciones

Servidor RPCon(#'basic.deliver'{}, #amqp_msg{props = Props, payload = Payload}) ->

CorrelationId = Props.correlation_id,

ReplyTo = Props.reply_to,

Reply = process_request(Payload),

NewProps = #'P_basic'{correlation_id = CorrelationId},

publish("", %% anonymous exchange#amqp_msg{props = NewProps,

payload = Reply}, ReplyTo). %% routing key

Monday, July 4, 2011

Page 98: Desacoplando aplicaciones

Patrones Avanzados

Monday, July 4, 2011

Page 99: Desacoplando aplicaciones

Control Bus

How can we effectively administer a messaging system that is distributed across multiple

platforms and a wide geographic area?

Monday, July 4, 2011

Page 100: Desacoplando aplicaciones

Control Bus

Use a Control Bus to manage an enterprise

integration system.

Monday, July 4, 2011

Page 101: Desacoplando aplicaciones

Control Bus

• Send Configuration Messages

• Start/Stop Services

• Inject Test Messages

• Collect Statistics

Monday, July 4, 2011

Page 102: Desacoplando aplicaciones

Control Bus

Monday, July 4, 2011

Page 103: Desacoplando aplicaciones

Control Bus

Make Services “Control Bus” Enabled

Monday, July 4, 2011

Page 104: Desacoplando aplicaciones

Detour

How can you route a message through intermediate steps to perform validation,

testing or debugging functions?

Monday, July 4, 2011

Page 105: Desacoplando aplicaciones

Detour

Construct a Detour with a context-based router controlled via the Control Bus.

In one state the router routes incoming messages through additional steps while in the other it routes

messages directly to the destination channel.

Monday, July 4, 2011

Page 106: Desacoplando aplicaciones

Detour

Monday, July 4, 2011

Page 107: Desacoplando aplicaciones

Wire Tap

How do you inspect messages that travel on a point-to-point channel?

Monday, July 4, 2011

Page 108: Desacoplando aplicaciones

Wire Tap

Insert a simple Recipient List into the channel that publishes each incoming message to the main

channel and a secondary channel.

Monday, July 4, 2011

Page 109: Desacoplando aplicaciones

Wire Tap

Monday, July 4, 2011

Page 110: Desacoplando aplicaciones

Smart Proxy

How can you track messages on a service that publishes reply messages to the Return Address

specified by the requestor?

Monday, July 4, 2011

Page 111: Desacoplando aplicaciones

Smart Proxy

Use a Smart Proxy to store the Return Address supplied by the original requestor and replace it with the

address of the Smart Proxy.

When the service sends the reply message route it to the original Return

Address.

Monday, July 4, 2011

Page 112: Desacoplando aplicaciones

Smart Proxy

Monday, July 4, 2011

Page 113: Desacoplando aplicaciones

Créditos

Imágenes y descripciones de los patrones tomadas de:http://www.eaipatterns.com/

Monday, July 4, 2011

Page 114: Desacoplando aplicaciones

¡Gracias!

@old_soundhttp://vimeo.com/user1169087

http://www.slideshare.net/old_sound

Monday, July 4, 2011