Forwarder-Receiver

Pattern Oriented
Software Architecture
Forwarder-Receiver
Jamir Antonio Avila Mojica
Cesar Julio Bustacara Medina
Agenda
Introducción
Patrón Forwarder-Receiver
Ejemplo
Contexto
Problema
Solución
Estructura
Dinámica
Variantes
Usos conocidos
Introducción
Comunicación.
• Estos patrones ayudan a organizar la
Comunicación entre componentes.
• Solamente unos pocos sistemas de
mediana y gran escala corren en un único
computador, la mayoría de ellos usan
redes de computadores.
Introducción
• Los sistemas distribuidos permiten
compartir y utilizar recursos disponibles
en la red.
• Máquinas rápidas y costosas pueden alojar
servicios centrales como sistemas de
administración de bases de datos, mientras
que máquinas más económicas pueden
acceder a estos servicios de forma
remota.
• En las compañías el trabajo es
inherentemente distribuido
Introducción
• Para que los sistemas distribuidos
colaboren es necesario que se
comuniquen unos con otros. Sin embargo,
el problema es que hay muchos
mecanismos de comunicación.
• Hay que reducir el acoplamiento entre los
componentes de un sistema distribuido y
los mecanismos que usa para
comunicarse. Dos aspectos claves son el
encapsulamiento y la transparencia de
ubicación.
Introducción
• El encapsulamiento de la comunicación
facilita ocultar los detalles de comunicación
a los usuarios. Normalmente mediante una
interfaz de programación sobre las
facilidades de comunicación de bajo nivel.
• La transparencia de ubicación permite a
las aplicaciones acceder a los
componentes remotos sin conocer su
ubicación física.
Introducción
Dos patrones abordan estos tópicos
• Forwarder-Receiver. Proporciona
comunicación entre procesos transparente
para sistemas de software en un modelo de
interacción compañero-compañero.
• Client-Dispatcher-Server. Proporciona
transparencia y oculta los detalles del
establecimiento de la comunicación entre
clientes y servidores.
Patrón Forwarder-Receiver
• Proporciona comunicación entre
procesos transparente para sistemas de
software en un modelo de interacción punto
a punto.
• Introduce forwarders y receivers para
desacoplar los puntos de los
mecanismos de comunicación.
Ejemplo
• Una compañía ofrece aplicaciones para la
administración de redes de computadores.
• Posee agentes responsables de observar y
monitorear eventos y recursos
Contexto
• Comunicación punto a punto.
Problema
• Una forma común de construir aplicaciones
distribuidas es usar los mecanismos de
bajo nivel disponibles para comunicación
entre procesos (IPC) como TCP/IP,
sockets o colas de mensajes.
• Proporcionados por casi todos los sistemas
operativos, y son muy eficientes
comparados con mecanismos de mayor
nivel como las llamadas a procedimientos
remotos.
Problema
• Sin embargo, estos mecanismos
introducen dependencias en protocolos
de red y sistemas operativos.
• Usando un mecanismo específico, la
solución resultante restringe la
portabilidad, la capacidad del sistema de
soportar entornos heterogéneos y hace
difícil cambiar el mecanismo de IPC
después.
Problema
• El patrón Forwarder-Receiver es útil
cuando necesite balancear las siguientes
fuerzas:
– Debe permitir la intercambiabilidad de los
mecanismos de comunicación.
– La cooperación de componentes sigue un
modelo punto a punto, en el que el emisor
solamente necesita conocer los nombres de
sus receptores.
– La comunicación entre puntos no debe tener
mayor impacto en el rendimiento.
Solución
• Peers distribuidos colaboran para resolver
un problema particular.
• Un peer puede actuar como:
– Un cliente
– Solicitar servicios
– Un servidor
– Proporcionar un servicio
– Ambos (cliente y servidor)
Solución
• Los detalles del mecanismo IPC para
enviar o recibir mensajes son ocultos
encapsulando esta funcionalidad
específica en componentes separados.
• Ejemplos de esta funcionalidad son:
– las transformaciones de nombres a
ubicaciones físicas
– el establecimiento de los canales de conexión
– el marshaling / unmarshaling de mensajes.
Estructura
• Consiste de tres tipos de componentes:
forwarders, receivers y peers:
Estructura
• Los componentes peers son responsables de
tareas de aplicación. Para cumplir sus tareas
requieren comunicación con otros peers. Estos
pueden estar localizados en procesos diferentes,
e incluso en una máquina diferente. Cada peer
conoce los nombres de los peers remotos con los
que necesita comunicarse.
Estructura
• Los componentes forwarder envían
mensajes que atraviesan los límites del
proceso.
• Proporciona una interfaz general que es
una abstracción de un mecanismo IPC
particular, e incluya funcionalidad para
hacer el marshal y entrega de mensajes.
• Cuando un forwarder envía un mensaje a
un peer remoto, determina la ubicación
física del receptor usando su
transformación nombre a dirección.
Estructura
• En el mensaje transmitido el forwarder
especifica su nombre, para que el peer
remoto pueda enviar la respuesta a quien
originó el mensaje.
Estructura
• Los componentes receiver son
responsables de recibir los mensajes. Un
receiver ofrece una interfaz general que es
también una abstracción de un mecanismo
IPC particular. Incluye la funcionalidad para
recibir y hacer el unmarshal de mensajes.
Estructura - Funcionalidad
• Envió de Mensajes:
– Para enviar un mensaje a un peer remoto, el
peer invoca el método sendMsg de su
forwarder, pasando el mensaje como
argumento.
– El método sendMsg debe convertir los
mensajes a un formato que entienda el
mecanismo IPC seleccionado. Para ello,
invoca marshal, y usa deliver para transmitir el
mensaje de datos al receiver remoto.
Estructura - Funcionalidad
• Recepción de Mensajes:
– Cuando el peer quiere recibir un mensaje de
un peer remoto, invoca el método receiveMsg
de su receiver, y el mensaje es retornado.
– receiveMsg invoca receive, quien usa la
funcionalidad del mecanismo IPC para recibir
mensajes, luego llama unmarshal para
convertir el mensaje a un formato que entienda
el peer.
Dinámica
• El siguiente escenario ilustra un típico ejemplo
del uso de la estructura Forwarder-Receiver. Dos
peers P1 y P2 comunican entre sí. Para esto, P1
usa un forwarder Forw1 y un receiver Recv1. P2
maneja sus transferencias de mensajes con un
forwarder Forw2 y un receiver Recv2:
– P1 solicita un servicio del peer remoto P2. Para ello
envía la solicitud a su forwarder Forw1 y especifica el
nombre del receptor.
– Forw1 determina la ubicación física del peer remoto y
hace el marshal del mensaje.
– Forw1 entrega el mensaje al receiver remoto Recv2.
Dinámica
– En algún momento anterior P2 ha solicitado a su
Recv2 esperar solicitudes entrantes. Ahora, Recv2
recibe el mensaje que llega de Forw1.
– Recv2 hace el unmarshal del mensaje y lo pasa a su
peer P2.
– Mientras tanto, P1 llama a su receptor Recv1 en
espera de una respuesta.
– P2 ejecuta el servicio solicitado, y envía el resultado y
el nombre del receptor P1 al forwarder Forw2. El
forwarder hace el marshal del resultado y lo entrega a
Recv1.
– Recv1 recibe la respuesta de P2, hace el unmarshal y
lo entrega a P1.
Dinámica
Implementación
• Para implementar el patrón de diseño ForwarderReceiver, itere los siguientes pasos:
– Especifique una transformación nombre a
dirección. Un nombre puede hacer referencia a un
grupo de direcciones no necesariamente a una
dirección única.
Implementación
– Especifique los protocolos de mensajes que van a
ser usados entre peers y forwarders. Este protocolo
define la estructura detallada del mensaje de datos
que un forwarder recibe de su peer. Haga lo mismo
para el protocolo de mensajes usados entre receivers
y peers. El siguiente es un ejemplo de mensaje
enviado entre peers y forwarders y viceversa:
class Message {
public String sender;
public String data;
public Message(String theSender, String rawData) {
sender = theSender;
data = rawData;
}
}
Implementación
• Seleccione un mecanismo de comunicación.
La decisión se debe tomar de acuerdo con los
mecanismos de comunicación disponibles en el
sistema operativo. Considere también:
– Es importante ser eficiente. Un mecanismo de bajo
nivel puede ser muy eficiente y flexible en cuanto a los
protocolos de comunicación que se pueden construir.
– Los mecanismos de bajo nivel requieren gran esfuerzo
de programación, y son dependientes de la plataforma
que se utilice.
• Para el ejemplo se seleccionó usar sockets.
Implementación
• Implemente el forwarder. Encapsule toda la
funcionalidad para enviar mensajes fuera de los
límites del proceso en el forwarder.
El forwarder proporciona esta funcionalidad a través de
su interfaz pública y encapsula los detalles de un
mecanismo de IPC particular.
Defina un almacén que transforme nombres a
direcciones físicas. El forwarder lo accede para
recuperar las direcciones físicas de los receptores
antes de establecer el enlace al peer remoto. Este
almacén puede ser dinámico, modificable con el
tiempo, o estático. Decida si cada forwarder tiene su
propio almacén o si hay uno compartido por todos.
Implementación
• En el ejemplo se usa la dirección IP acompañada por el
número de socket:
class Entry {
private String destinationId; // máquina destino
private int portNr; // número de puerto
public Entry(String theDest, int thePort) {
destinationId = theDest;
portNr = thePort;
}
public String dest() {
return destinationId;
}
public int port() {
return portNr;
}
}
class Registry {
private Map<Entry> hTable = new Hashtable<Entry>();
public void put(String theKey, Entry theEntry) {
hTable.put(theKey, theEntry);
}
public Entry get(String aKey) {
return hTable.get(theKey);
}
}
Implementación
• El constructor de la clase Forwarder espera un
argumento theName de tipo String que especifica
el nombre lógico del peer. Cuando un peer invoca
el método sendMsg ocurre lo siguiente:
– El método sendMsg invoca el método marshal para
convertir el mensaje a una secuencia de bytes.
– El método deliver es invocado. Este método busca la
dirección física del peer remoto en el almacén local.
• Para ello, la clase global fr contiene un miembro
fr.reg que es una instancia de Repository.
• deliver abre un socket, se comunica con el peer
remoto, transmite el mensaje y cierra los sockets.
Implementación
class Forwarder {
private Socket s;
private Outputstream oStr;
private String myName;
public Forwarder(String theNarne) {
myName = theName;
}
private byte[] marshal (Message theMsg) {
/ * . . . */
}
private void deliver(String theDest, byte[] data) {
try {
Entry entry = fr.reg.get(theDest);
s = new Socket(entry.dest(), entry.port());
oStr = s.getOutputStream();
oStr.write(data);
oStr.flush();
oStr.close();
s.close();
} catch (IOException e) { /* . . . */ }
}
public void sendMsg (String theDes t , Message theMsg) {
deliver(theDest, marshal(theMsg));
}
}
Implementación
• Implemente el receiver. Encapsule toda la
funcionalidad para recibir mensajes en el
receiver.
Proporcione al receiver con una interfaz general
que abstraiga los detalles de un mecanismo
particular IPC.
El receiver necesita incluir funcionalidad para
recibir y unmarshaling los mensajes. Con el
patrón Whole-part cada una de estas
responsabilidades se puede descomponer en
una parte separada del componente receiver.
Implementación
• Además, como los peers corren
asincrónicamente, se debe decidir si los receivers
deben bloquearse hasta que llegue un mensaje.
– Si es así, el receiver espera un mensaje entrante.
Solamente regresa el control a su peer cuando llegue
el mensaje. Esto es apropiado cuando el peer dependa
del mensaje entrante para continuar su tarea.
– En los demás casos, se deben implementar receivers
no bloqueantes que permite a los peers especificar
valores de time-out. En caso de que no llegue un
mensaje en el tiempo especificado, el receiver regresa
una excepción a su peer.
Implementación
• Si el mecanismo de IPC no soporta I/O no bloqueante,
debe usarse un hilo separado en el peer para manejar la
comunicación.
• El uso de más de un canal de comunicación con los
receivers es otra decisión importante de diseño. Tales
receivers son capaces de demultiplexar los canales de
comunicación – esperan hasta que un mensaje llegue en
uno de los canales y regresa el mensaje a su peer.
• Como es posible que más de un mensaje llegue al mismo
tiempo, los receiver pueden proporcionar una cola de
mensajes interna para hacer el buffer de mensajes. El
servicio del sistema select en UNIX permite esperar por
eventos en un conjunto de descriptores de archivos y
sockets.
Implementación
• En el ejemplo, si un peer instancia un receiver, llama al
constructor y pasa su propio nombre como argumento.
• El receiver usa este nombre para determinar que socket
usar para la recepción del mensaje. Cuando un peer
quiere recuperar un mensaje, llama al método receiveMsg
del objeto Receiver, quien a su vez invoca el método
receive. El método receive hace lo siguiente:
– Después de recuperar el número del puerto del almacén, abre un
server socket y espera las conexiones de los peers remotos.
– Tan pronto se establece la conexión, el mensaje y su tamaño son
leídos, receive retorna los datos a receiveMsg.
• Finalmente, receiveMsg invoca unmarshal para convertir
la secuencia de bytes en un objeto Message y regresa
este objeto al peer.
Implementación
class Receiver {
private ServerSocket srvS;
private Socket s;
private InputStream iStr;
private String myName;
public Receiver(String theName) {
myName = theName;
}
private Message unmarshal(byte[] anArray) {/*...*/ }
private byte[] receive() {
int val;
byte buffer[] = null;
try {
Entry entry = fr.reg.get(myName);
srvS = new ServerSocket(entry.port(), 1000);
s = srvS.acdept();
iStr = s.getInputStream();
val = iStr.accept();
buffer = new byte[val];
iStr.read(buffer);
iStr.close();
s.close();
srvS.close();
} catch (IOException e) { /* . . . */ }
return buffer;
}
public Message receiveMsg() {
return unmarshal(receive());
}
}
Implementación
• – Implemente los peers de la aplicación.
– Particione los peers en dos conjuntos: clientes
y servidores.
– La intersección de ambos no necesariamente
es vacía.
– Si un peer actúa como cliente, envía un
mensaje a un peer remoto y espera la
respuesta. Después de que haya recibido la
respuesta, continúa con su tarea.
– Los peers actúan como servidores esperando
contínuamente mensajes entrantes.
Implementación
• Cuando llegan los mensajes, ejecutan un servicio
que depende del mensaje recibido y envían la
respuesta al origen.
• La comunicación entre los peers no siempre es
de dos vías. Algunas veces es suficiente para un
peer enviar un mensaje a otro sin requerir
respuesta; hay peers que envían mensajes y
continúan con su trabajo. Esta comunicación de
una vía permite una comunicación asincrónica
entre emisores y receptores.
Implementación
• A continuación hay un ejemplo de un peer
actuando como servidor:
class Server extends Thread {
Receiver r;
Forwarder f;
public void run() {
Message result = null;
r = new Receiver("Server");
result = r.receiveMsg();
f = new Forwarder("Server");
Message msg = new Message("Server", "I'm alive");
f.sendMsg(result.sender, msg);
}
}
Implementación
• Implemente una configuración inicial. Cuando el sistema
sea iniciado, forwarders y receivers deben contar con una
transformación válida nombre a dirección. Introduzca una
rutina separada de inicialización que crea un depósito e
ingrese las parejas nombre / dirección.
class Configuracion {
public Configuracion() {
Entry entry = new Entry(“127.0.0.1”, 1111);
fr.reg.put(“Client”, entry);
entry = new Entry(“127.0.0.1”, 2222);
fr.reg.put(“Server”, entry);
}
}
Variantes
• Forwarder – Receiver sin
transformación nombre a dirección.
Algunas veces el rendimiento es más
importante que ser capaz de encapsular
todos los detalles del mecanismo IPC.
Usos conocidos
• El toolkit de desarrollo de software TASC soporta
la implementación de estructuras ForwarderReceiver en aplicaciones distribuidas para
sistemas de automatización de fábricas.
• Los sistemas de switches ATM-P usan el patrón
de diseño Forwarder-Receiver para implementar
IPC entre los componentes distribuidos
estáticamente.
• También es usado para implementar
comunicación entre procesos en el entorno
distribuido de Smalltalk BrouHaHa
Consecuencias
• Ventajas
– Comunicación eficiente entre procesos. El patrón
facilita la elaboración de mecanismos de comunicación
entre procesos muy eficientes.
– Encapsulamiento de facilidades IPC. Todas las
dependencias de IPC concretos son encapsuladas en
los forwarders y receivers.
• Desventajas
– No soporta reconfiguración flexible de
componentes. Los sistemas forwarder–receiver son
difíciles de adaptar si la distribución de los peers
cambia en tiempo de ejecución.
Bibliografía
• Pattern-Oriented Software Architecture: A
System of Patterns, F. Buschmann, R. Meunier,
H. Rohnert, P. Sommerlad, M. Stal. John Wiley &
Sons, 1996
• Blackboard Architectures, JayDee Technology
Ltd. John Hunt, 2002, Blackboard Systems,
Blackboard Technology Group, Inc, Daniel D.
Corkill