Descargar

Patrón CallBack (página 2)


Partes: 1, 2

 

Implementación:

La figura muestra el diagrama de componentes del patrón CallBack

En la figura del diagrama se muestra la secuencia del patrón CallBack

Este patrón impone algunos requerimientos básicos en el cliente y en el servidor:

  • Cliente: el cliente debe proporcionar una interfaz de retornollamada para el servidor, de forma que este pueda contactar con el cliente cuando haya finalizado la petición.
  • Servidor: más allá de la interfaz tradicional del cliente, el servidor necesita alguna forma de indicar a los clientes cuando ha acabado el procesamiento. Además, el servidor debe ser capaz de procesar y, posiblemente, almacenar las peticiones del cliente.

Ventajas en inconvenientes:

La mayor ventaja del patrón Callback es la mejora en la eficiencia del sistema especialmente en el rendimiento del servidor. La mayoría de mejoras se pueden ver en dos áreas distintas:

  • Procesamiento en el servidor: el servidor no tiene que mantener los threads de comunicación para servir a los clientes, por lo que puede canalizar esos recursos hacia peticiones de procesamiento de los clientes o en atender a llamadores. Además, el servidor puede realizar el procesamiento cuando lo considere adecuado; no tiene por que ser el mismo instante que recibe la petición.
  • Comunicación en el servidor: el servidor no tiene que mantener una conexión abierta mientras el cliente espera los resultados. Esto significa que un servidor puede soportar un mayor número de llamadores con unos recursos de comunicación limitados, como, por ejemplo, ocurriría con los sockets (conectores).

Esa es precisamente la mayor motivación para utilizar el patrón CallBack en los sistemas. En los casos más extremos, puede significar la diferencia entre tener un grupo de servidores en paralelo y utilizar una maquina para atender las peticiones de los clientes.

Otra ventaja es que el cliente no tiene que esperar el procesamiento completo del servidor y puede continuar con otras tareas. El cliente puede seguir con lo que estaba haciendo mientras espera la respuesta del servidor. Cuando el resultado esté disponible, éste puede ser mostrado de forma inmediata.

Dependiendo de la implementación del patrón, las peticiones de los clientes pueden ponerse en cola, permitiendo que el servidor organice y priorice su carga de trabajo. También permite que el servidor notifique a los clientes cuando suceden cambios mas halla del tiempo de vida habitual de un cliente. Los agentes Web son un buen ejemplo de esto, porque permiten que los clientes introduzcan una petición en una sesión Web y reciban una notificación de otra sesión.

Un desafió del patrón Callback es que necesita que un cliente escuche las retrollamadas del servidor. Esto a menudo hace que el código del cliente se mas completo, e incrementa la carga de los sistemas cliente. Un inconveniente adicional surge del hecho de que Callback desacopla la petición del cliente. Eso suele dificultar la cancelación o modificación de una petición una vez que ha sido enviada al servidor.

Variaciones del Patrón:

Las variaciones del patrón Callback se centran generalmente en las estrategias de procesamiento del servidor y en las aproximaciones sobre las notificaciones a los clientes. Las dos aproximaciones principales para el procesamiento en el lado del servidor son:

  • Procesamiento directo: con esta aproximación, el servidor crea un thread trabajador para satisfacer las peticiones de los clientes. La implementación resulta sencilla, pero esto puede ser complicado de escalar para un gran número de peticiones de servicio.
  • Cola de patrones: el servidor mantiene una cola con las peticiones de los clientes y un pool de threads trabajadores. Los threads trabajadores son asignados para ejecutar el procesamiento de los clientes de forma continua.

Solo hay opciones disponibles para notificaciones de los clientes, dependiendo de los requisitos de las aplicaciones:

  • Retrollamada activa: un cliente utiliza un proceso similar a un servidor para escuchar las comunicaciones entrantes. Eso permite que el cliente reciba directamente la notificación del servidor.
  • Sondeo del cliente: necesita que el cliente revise periódicamente el estado de su petición. Cuando la petición, o una parte de ella se haya completado, el cliente solicitara la información correspondiente al servidor.
  • Reconocimiento explicito: un servidor puede retrasmitir un mensaje hasta que recibe una confirmación del cliente. Esta aproximación se suele utilizar cuando el procesamiento en el servidor puede durar un tiempo mucho mayor que el tiempo de vida del cliente. Aunque esto no es relevante en TCP porque los sockets no permanecen abiertos a menos que el cliente este presente para hacer su trabajo, si resulta significativo cunado se utilizan tecnologías de comunicación no confiables UDP.

Patrones relacionados:

Entre lo patrones relacionados con Callback se incluye Worker Thread. El patrón worker Thread es utilizado para ayudar a planificar las peticiones de los clientes.

Las peticiones se sitúan en una cola, y los threads trabajadores procesan.

Ejemplo:

CallbackServer.java

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface CallbackServer extends Remote{

public void getProject(String projectID, String callbackMachine,

String callbackObjectName) throws RemoteException;

}

CallbackServerImpl.java

import java.rmi.Naming;

import java.rmi.server.UnicastRemoteObject;

public class CallbackServerImpl implements CallbackServer{

private static final String CALLBACK_SERVER_SERVICE_NAME = "callbackServer";

public CallbackServerImpl(){

try {

UnicastRemoteObject.exportObject(this);

Naming.rebind(CALLBACK_SERVER_SERVICE_NAME, this);

}

catch (Exception exc){

System.err.println("Error using RMI to register the CallbackServerImpl " + exc);

}

}

public void getProject(String projectID, String callbackMachine,

String callbackObjectName){

new CallbackServerDelegate(projectID, callbackMachine, callbackObjectName);

}

}

CallbackServerDelegate.java

import java.net.MalformedURLException;

import java.rmi.Naming;

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

public class CallbackServerDelegate implements Runnable{

private Thread processingThread;

private String projectID;

private String callbackMachine;

private String callbackObjectName;

public CallbackServerDelegate(String newProjectID, String newCallbackMachine,

String newCallbackObjectName){

projectID = newProjectID;

callbackMachine = newCallbackMachine;

callbackObjectName = newCallbackObjectName;

processingThread = new Thread(this);

processingThread.start();

}

public void run(){

Project result = getProject();

sendProjectToClient(result);

}

private Project getProject(){

return new Project(projectID, "Test project");

}

private void sendProjectToClient(Project project){

try{

String url = "//" + callbackMachine + "/" + callbackObjectName;

Object remoteClient = Naming.lookup(url);

if (remoteClient instanceof CallbackClient){

((CallbackClient)remoteClient).receiveProject(project);

}

}

catch (RemoteException exc){}

catch (NotBoundException exc){}

catch (MalformedURLException exc){}

}

}

CallbackClient.java

import java.rmi.Remote;

import java.rmi.RemoteException;

public interface CallbackClient extends Remote{

public void receiveProject(Project project) throws RemoteException;

}

CallbackClientImpl.java

import java.net.InetAddress;

import java.net.MalformedURLException;

import java.net.UnknownHostException;

import java.rmi.Naming;

import java.rmi.server.UnicastRemoteObject;

import java.rmi.NotBoundException;

import java.rmi.RemoteException;

public class CallbackClientImpl implements CallbackClient{

private static final String CALLBACK_CLIENT_SERVICE_NAME = "callbackClient";

private static final String CALLBACK_SERVER_SERVICE_NAME = "callbackServer";

private static final String CALLBACK_SERVER_MACHINE_NAME = "localhost";

private Project requestedProject;

private boolean projectAvailable;

public CallbackClientImpl(){

try {

UnicastRemoteObject.exportObject(this);

Naming.rebind(CALLBACK_CLIENT_SERVICE_NAME, this);

}

catch (Exception exc){

System.err.println("Error using RMI to register the CallbackClientImpl " + exc);

}

}

public void receiveProject(Project project){

requestedProject = project;

projectAvailable = true;

}

public void requestProject(String projectName){

try{

String url = "//" + CALLBACK_SERVER_MACHINE_NAME + "/" + CALLBACK_SERVER_SERVICE_NAME;

Object remoteServer = Naming.lookup(url);

if (remoteServer instanceof CallbackServer){

((CallbackServer)remoteServer).getProject(projectName,

InetAddress.getLocalHost().getHostName(),

CALLBACK_CLIENT_SERVICE_NAME);

}

projectAvailable = false;

}

catch (RemoteException exc){}

catch (NotBoundException exc){}

catch (MalformedURLException exc){}

catch (UnknownHostException exc){}

}

public Project getProject(){ return requestedProject; }

public boolean isProjectAvailable(){ return projectAvailable; }

}

Bibliografía:

Patrones de diseño aplicados a JAVA

STEPHEN STELTING /OLAV MAASSEN

 

Darwin Vélez Vargas

Universidad Tecnológica Equinoccial

Técnicas Avanzadas de Programación

2006/06/30

6to "A" Informática

Partes: 1, 2
 Página anterior Volver al principio del trabajoPágina siguiente