Paradigmas avanzados de computación distribuida

Anuncio
Paradigmas avanzados de computación distribuida
En los capítulos anteriores se han explorado un diverso número de paradigmas
inicialmente presentados en el Capítulo 3, donde se mostraba una jerarquía de
paradigmas repetida aquí en la Figura 12.1.
FIGURA 12.1: Los paradigmas de computación distribuida y su nivel de abstracción.
Este capítulo presenta alguno de los paradigmas más avanzados. Algunos de ellos
están siendo aún investigados, mientras que otros son usados ampliamente en la
práctica. Especialmente, este capítulo dará una visión general de los siguientes
paradigmas de computación distribuida: sistemas de colas de mensajes, agentes
móviles, servicios de red, espacios de objetos y computación colaborativa.
Paradigma de sistemas de colas de mensajes
El paradigma de sistemas de colas de mensajes, también denominado middleware
orientado a mensajes (MOM, message-oriented middleware), es una elaboración
del paradigma de paso de mensajes. En este paradigma, un sistema de mensajes actúa
como intermediario entre procesos separados e independientes.
FIGURA 12.2: Paradigma de sistemas de colas de mensajes.
La Figura 12.2 ilustra el paradigma. Los mensajes se envían al sistema de mensajes,
que actúa de conmutador de los mismos, encaminándolos a los receptores apropiados.
A través de un sistema de mensajes, los procesos intercambian mensajes de forma
asíncrona, de una manera desacoplada. Un emisor deposita un mensaje en el sistema,
el cual lo reenvía a una cola de mensajes asociada con cada receptor. Una vez que el
mensaje se ha enviado, el emisor se libera para poder realizar otras tareas. El mensaje
se reenvía por parte del sistema de mensajes hasta los clientes. Cada cliente puede
extraer de su cola bajo demanda.
Los modelos de sistemas de colas de mensajes se pueden clasificar en dos subtipos,
punto-a-punto y publicación/suscripción, que se describen a continuación:
Modelo de mensajes punto-a-punto
El modelo mostrado en la Figura 12.2 se corresponde con el modelo de mensajes
punto-a-punto. En este modelo, un sistema de mensajes redirige un mensaje desde el
emisor hasta la cola de mensajes del receptor. A diferencia del modelo básico de paso
de mensajes, el modelo de mensaje punto-a-punto proporciona un depósito de los
mensajes que permite que el envío y la recepción estén desacoplados.
Comparado con el modelo básico de paso de mensajes, este paradigma proporciona
una abstracción adicional para operaciones asíncronas: No existe un bloqueo entre
emisor y receptor.
Modelo de mensajes publicación/suscripción
En este modelo, mostrado en la Figura 12.3, cada mensaje se asocia con un
determinado tema o evento. Las aplicaciones interesadas en el suceso de un evento
específico se pueden suscribir a los mensajes de dicho evento. Cuando ocurre el
evento que se aguarda, el proceso publica un mensaje anunciando el evento o asunto.
El sistema de cola de mensajes distribuye el mensaje a todos los suscriptores.
FIGURA 12.3: El modelo de sistema de mensajes publicación/suscripción.
El modelo de mensajes publicación/suscripción ofrece una potente abstracción para
multidifusión o comunicación en grupo. La operación publicar permite al proceso
difundir a un grupo de procesos, y la operación suscribir permite a un proceso
escuchar dicha difusión de mensajes.
El paradigma de sistema de mensajes se emplea comercialmentre de forma muy
amplia en aplicaciones distribuidas. Existe un gran número de herramientas que dan
soporte a este paradigma. Algunas de ellas son:
 MQ*Series de IBM (rebautizado como WebSphere MQ) [4.ibm.com, 3],
 Microsoft’s Message Queue (MSMQ) [microsoft.com, 2],
 Java Message Service (JMS) [java.sun.com, 1] disponible con el J2EE SDK
[java.sun.com, 4] versiones 1.3 o superiores.
Para aquellos estudiantes interesados en una API que dé soporte a un modelo de
sistema de paso de mensajes, JMS es un buen punto de arranque.
La Figura 12.4 y la Figura 12.5 muestran un ejemplo de programación con JMS. Un
EmisorMensaje envía un mensaje a una cola JMS, mientras que ReceptorMensaje lo
recibe de la cola. Para poder apreciar el asíncronismo que el sistema de cola de
mensajes proporciona, deberá experimentar arrancando una o varias copias de
ReceptorMensaje, y posteriormente el EmisorMensaje. Cada uno de los clientes debe
recibir un mensaje (“¡Hola Mundo!”) una vez que se ha enviado. (Nota: Los
programas de ejemplo sólo compilarán y ejecutarán en un sistema que tenga instalado
JMS; consulte [java.sun.com, 1] para obtener información sobre cómo descargar e
instalar JMS.)
FIGURA 12.4: Un ejemplo de un emisor de mensajes punto-a-punto.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* La clase EmisorMensaje manda un mensaje "¡Hola Mundo!" a
* una cola de mensajes de Java Message System (JMS). Este
* programa está preparado para ejecutarse con la clase
* ReceptorMensaje, que recibe el mensaje vía el servicio
* JMS.
* Para ejecutar el programa: El proveedor JMS debe estar
* arrancado y se debe haber creado una cola. El nombre de
* la cola se debe especificar como una rgumento en la línea
* de mandatos al arrancar el programa.
* M. Liu, basado en los ejemplos del
* tutorial http://java.sun.com/products/jms/tutorial/
*/
import javax.jms.*; // para las clases JMS
import javax.naming.*; // para las clases JNDI
public class EmisorMensaje {
public static void main(String[] args) {
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
String nombreCola = null;
Context contextoJNDI = null;
QueueConnectionFactory fabricaConexiones
= null;
QueueConnection conexionCola = null;
QueueSession sesionCola = null;
Queue cola = null;
QueueSender emisorCola = null;
TextMessage mensaje = null;
final int NUM_MSGS;
if ( (args.length != 1) ) {
System.out.println("Uso: java " +
"EmisorMensaje <nombre-cola>");
System.exit(1);
}
nombreCola = new String(args[0]);
System.out.println("Nombre de la cola es " + nombreCola);
/* Crea un objeto InitialContext de JNDI si
no existe ningunao. */
try {
contextoJNDI = new InitialContext();
} catch (NamingException e) {
System.out.println("No se ha podido crear el contexto " +
"JNDI: " + e.toString());
System.exit(1);
}
/* Búsqueda de la fábrica de conexiones y la cola. Si
alguna de las dos no existe. */
try {
fabricaConexiones =
(QueueConnectionFactory)
contextoJNDI.lookup("QueueConnectionFactory")
cola = (Queue) contextoJNDI.lookup(nombreCola);
} catch (NamingException e) {
System.out.println("Búsqueda JNDI fallida: " +
e.toString());
System.exit(1);
}
try {
/* crear conexión */
conexionCola =
fabricaConexiones.createQueueConnection();
/* crear sesión */
sesionCola =
conexionCola.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
/* crear emisor y objeto mensaje. */
emisorCola = sesionCola.createSender(cola);
mensaje = sesionCola.createTextMessage();
/* definir mensaje */
mensaje.setText("¡Hola Mundo!");
System.out.println("Enviando mensaje: " +
mensaje.getText());
/* enviar a JMS */
emisorCola.send(mensaje);
} catch (JMSException e) {
System.out.println("Ha ocurrido una excepción: " +
88
e.toString());
89
} finally {
90
/* cerrar la cola de conexión */
91
if (conexionCola != null) {
92
try {
93
conexionCola.close();
94
} catch (JMSException e) {}
95
}
96
} //fin finally
97
} //fin main
98 } //fin class
FIGURA 12.5: Un ejemplo de un receptor de mensajes punto-a-punto.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
* La clase ReceptorMensaje se debe usar junto con
* la clase EmisorMensaje, la cual manda un mensaje
* via the JMS.
* Se debe dar el mismo nombre de cola que en EmisorMensaje
* por medio de un argumento en la líne de mandatos
* M. Liu, basado en los ejemplos del
* Tutorial,http://java.sun.com/products/jms/tutorial/
*/
import javax.jms.*;
import javax.naming.*;
public class ReceptorMensaje {
public static void main(String[] args) {
String nombreCola = null;
Context contextoJNDI = null;
QueueConnectionFactory fabricaConexiones
= null;
QueueConnection conexionCola = null;
QueueSession sesionCola = null;
Queue cola = null;
QueueReceiver receptorCola = null;
TextMessage mensaje = null;
if (args.length != 1) {
System.out.println("Uso: java " +
"ReceptoMensaje <nombre-cola>");
System.exit(1);
}
nombreCola = new String(args[0]);
System.out.println("Nombre de la cola es " + nombreCola);
/* Crea un objeto InitialContext de JNDI si
no existe ningunao. */
try {
contextoJNDI = new InitialContext();
} catch (NamingException e) {
System.out.println("No se ha podido crear el contexto " +
"JNDI: " + e.toString());
System.exit(1);
}
/* Búsqueda de la fábrica de conexiones y la cola. Si
alguna de las dos no existe. */
try {
fabricaConexiones =
(QueueConnectionFactory)
contextoJNDI.lookup("QueueConnectionFactory");
cola = (Queue) contextoJNDI.lookup(nombreCola);
} catch (NamingException e) {
System.out.println("Búsqueda JNDI fallida: " +
55
e.toString());
56
System.exit(1);
57
}
58
59
try {
60
/* crear conexión */
61
conexionCola =
62
fabricaConexiones.createQueueConnection();
63
/* crear sesión de la conexión */
64
sesionCola =
65
conexionCola.createQueueSession(false,
66
Session.AUTO_ACKNOWLEDGE);
67
/* crear un receptor */
68
receptorCola = sesionCola.createReceiver(cola);
69
conexionCola.start();
70
/* recibe el mensaje */
71
Message m = receptorCola.receive(1);
72
mensaje = (TextMessage) m;
73
System.out.println("Leyendo mensaje: " +
74
mensaje.getText());
75
} catch (JMSException e) {
76
System.out.println("Ha ocurrido una excepción: " +
77
e.toString());
78
} finally {
79
if (conexionCola != null) {
80
try {
81
conexionCola.close();
82
} catch (JMSException e) {}
83
}
84
}//fin finally
85
}//fin main
86 }//fin class
Se recomienda a los lectores interesados en más detalles sobre el API de JMS la
referencia [java.sun.com,1] que muestra más ejemplos, incluyendo los relativos al
modelo publicación/suscripción.
Agentes móviles
Un agente móvil es un paradigma de computación distribuida que ha interesado a los
investigadores desde los 80. Los agentes móviles se han convertido en
tecnológicamente viables gracias a las últimas tecnologías y hoy por hoy tienen el
potencial de revolucionar las aplicaciones en red.
En el contexto de la informática, un agente es un programa software independiente
que se ejecuta en representación del usuario.
Un agente móvil es un programa que, una vez lanzado por el usuario, puede viajar de
ordenador a ordenador autónomamente y puede continuar con sus función incluso si
el usuario se desconecta. La Figura 12.6 ilustra el concepto de un agente móvil.
FIGIRA 12.6: Un agente móvil viaja de un computador a otro.
Arquitectura básica
Un agente móvil es un objeto serializable – un objeto cuyos datos al igual que el
estado se pueden empaquetar para ser transmitidos por la red. El lector recordará el
término empaquetado de datos (data marshaling), introducido por primera vez en el
Capítulo 1, como el aplanamiento y codificación de estructuras de datos con el fin de
transmitirlas de un computador a otro. Un objeto se puede serializar y transmitir entre
dos ordenadores de la misma forma. Una vez llegado, el objeto se reconstruye y se
deserializa, con su estado restaurado como al momento de serializarse, y entonces el
objeto puede retomar su ejecución en el sistema donde acaba de llegar.
La arquitectura básica para dar soporte a agentes móviles se muestra en la Figura
12.7. Un objeto serializable, representando al agente móvil, se lanza en un
computador. El agente contiene los siguientes datos:
 Información de identidad – información que permite identificar al agente.
 Itinerario – una lista de direcciones de ordenadores que el agente debe visitar.
 Datos de la tarea – los datos que el agente requiere para realizar sus tareas, o
bien datos recogidos por el agente.
FIGURA 12.7: Un agente móvil viaja por varios ordenadores.
Un agente también lleva consigo la lógica (código) para realizar las tareas.
En cada parada, el agente llega a un servidor. A través del servidor de agentes, el
agente móvil usa los recursos locales para realizar sus tareas.
Como parte de la arquitectura, se necesita un servicio de directorio que permita al
agente buscar el servidor en cada parada. Cuando el agente ha concluido su tarea en
un sitio, el objeto agente se serializa, y, con la ayuda de un servidor de agentes, el
objeto se transporta al siguiente ordenador del itinerario.
Hay varios entornos que se han desarrollado para proporcionar arquitecturas de
soporte a agentes móviles, por ejemplo Aglet [Lange and Oshima,5;
aglets.sourceforge.net, 6], Concordia [merl.com, 7], y Grasshopper [grasshopper.de,
8]. Por simplicidad, sin embargo, se mostrará el concepto de agente móvil usando
objetos serializables y Java RMI. (Nota: La implementación presentada vale para
demostrar el concepto de agente móvil. Para verdaderos desarrollos, existen
consideraciones –a discutir – que la demostración no trata.)
La Figura 12.8 presenta la interfaz Java de un agente; la implementación de la interfaz
se ve en la Figura 12.9.
FIGURA 12.8: InterfazAgente.java.
// Una interfaz para un objeto transportable
// que representa un agente móvil
// M. Liu
import java.io.Serializable;
public interface InterfazAgente extends Serializable {
void ejecuta();
}
FIGURA 12.9: Agente.java.
1
2
3
4
5
6
7
// Una implementación de un agente móvil
import
import
import
import
import
java.io.*;
java.util.*;
java.rmi.*;
java.rmi.registry.Registry;
java.rmi.registry.LocateRegistry;
8
9 public class Agente implements InterfazAgente {
10
11
int indiceNodo; // cuál es el siguiente ordenador a visitar
12
String nombre;
13
Vector listaNodos; // el itinerario
14
int puertoRMI = 12345;
15
16
public Agente(String miNombre, Vector laListaComputadoras,
17
int elPuertoRMI ) {
18
nombre = miNombre;
19
listaNodos = laListaNodos;
20
indiceNodo = 0;
21
puertoRMI = elPuertoRMI;
22
}
23
24
// Este método define las tareas que realiza el agente
25
// móvil una vez que llega a un servidor.
26
public void ejecuta() {
27
String actual, siguiente;
28
dormir (2); // pausa para poder visualizarlo
29
System.out.println("¡Aquí el agente 007!");
30
actual = (String) listaNodos.elementAt(indiceNodo);
31
indiceNodo++;
32
if (indiceNodo < listaNodos.size()) {
33
// si hay más computadoras que visitar
34
siguiente = (String) listaNodos.elementAt(indiceNodo);
35
dormir (5); // pausa para poder visualizarlo
36
try {
37
// Localiza el registro RMI en el siguiente nodo
38
Registry registro = LocateRegistry.getRegistry
39
("localhost", puertoRMI);
40
ServerInterface h = (ServerInterface)
41
registro.lookup(siguiente);
42
System.out.println("Buscando " + siguiente +
43
" en " + actual + " completado ");
44
dormir (5); // pausa para poder visualizarlo
45
// Pide al servidor del siguiente nodo que reciba a
46
// este agente.
47
h.recibe(this);
48
} // fin try
49
catch (Exception e) {
50
System.out.println
51
("Excepción en el ejecuta del Agente: " + e);
52
}
53
} // fin if
54
else { //si se han hecho todas las paradas
55
dormir (5); // pausa para poder visualizarlo
56
System.out.println("El Agente 007 ha regresado a casa");
57
dormir (5); // pausa para poder visualizarlo
58
}
59
}
60
61
// El método dormir suspende la ejecución de este objeto
62
// un número determinado de segundos.
63
static void dormir (double time ){
64
try {
65
Thread.sleep( (long) (time * 1000.0));
66
}
67
catch (InterruptedException e) {
68
System.out.println ("excepción en dormir);
69
}
70
} // fin dormir
71
72 } // fin class Agente
El núcleo de la implementación del agente (Figura 12.9) está en su constructor (líneas
16–22) y en su método ejecuta (líneas 26–59). El constructor inicializa los datos de
estado del agente, incluyendo el itinerario y el índice al siguiente computador a visitar
en dicho itinerario. El método ejecuta contiene la lógica de las tareas que se espera
que el agente realice en cada ordenador. En esta demo, las tareas se resumen en la
salida de un simple mensaje (línea 56) y en la búsqueda del servidor de agentes de la
siguiente parada (líneas 32–53).
La implementación de servidor de agentes se muestra en las Figuras 12.10 y 12.11.
FIGURA 12.10: InterfazServidor.java.
// Fichero de interfaz del servidor de agentes - M. Liu
import java.rmi.*;
public interface InterazServidor extends Remote {
public void recibe(Agente h)
throws java.rmi.RemoteException;
}
El servidor, por su parte, se registra en el registro RMI y proporciona un método,
recibe, que el agente móvil invoca cuando está preparado para transportarse al
servidor. El método imprime un mensaje que anuncia la llegada del agente, y
posteriormente llama al método ejecuta del agente. Nótese que el método recibe
acepta como argumento el objeto agente serializable.
FIGURA 12.11: Servidor.java.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// Una
import
import
import
import
import
import
implemnetación de un servidor agentes
java.rmi.*;
java.rmi.server.*;
java.rmi.registry.Registry;
java.rmi.registry.LocateRegistry;
java.net.*;
java.io.*;
public class Servidor extends UnicastRemoteObject
implements InterfazServidor{
static int puertoRMI = 12345;
public Servidor() throws RemoteException {
super();
}
public void recibe(Agent h) throws RemoteException {
dormir (3); // pausa para poder visualizarlo
System.out.println
("*****El Agente " + h.name + " ha llegado." );
h.ejecuta();
}
public static void main(String args[]) {
InputStreamReader is = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(is);
String s;
String miNombre = "servidor" + args[0];
//Nota: Los servidores se espera que se arranquen con los
//argumentos 1, 2 y 3 de la línea de mandatos respectivamente,
try{
System.setSecurityManager(new RMISecurityManager());
Servidor h = new Servidor();
Registry registro =
LocateRegistry.getRegistry(puertoRMI);
registro.rebind( miNombre, h);
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
System.out.println("*******************************");
System.out.println(" Agente " + miNombre + " listo.");
System.out.println("*******************************");
}// fin try
catch (RemoteException re) {
System.out.println("Excepción en el main del Servidor: "
+ re);
} // fin catch
} // fin main
// El método dormir suspende la ejecución de este objeto
// un número determinado de segundos.
static void dormir (double time ){
try {
Thread.sleep( (long) (time * 1000.0));
}
catch (InterruptedException e){
System.out.println ("excepción en dormir");
}
} // fin dormir
} // fin class
Para finalizar, se necesita un programa cliente que cree una instancia y lance al agente
hacia la primera parada del itinerario. La implementación se muestra en la Figura
12.12.
FIGURA 12.12: Cliente.java.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//Cliente.java - programa cliente que lanza al agente móvil
// M. Liu
import
import
import
import
import
java.io.*;
java.util.*;
java.rmi.*;
java.rmi.registry.Registry;
java.rmi.registry.LocateRegistry;
public class Cliente {
static int puertoRMI = 12345;
public static void main(String args[]) {
System.setSecurityManager(new RMISecurityManager());
try {
Registry registro = LocateRegistry.getRegistry
("localhost", puertoRMI);
ServerInterface h = (ServerInterface)
registro.lookup("servidor1");
System.out.println
("Lookup for servidor1 completed " );
System.out.println("***Buen viaje, " +
" agent 007.");
Vector listaNodos = new Vector();
listaNodos.addElement("servidor1");
listaNodos.addElement("servidor2");
listaNodos.addElement("servidor3");
Agent a = new Agent("007", listaNodos, puertoRMI);
h.receive(a);
System.out.println("***Buen trabajo, 007");
}
catch (Exception e) {
System.out.println("Excepción en main: " + e);
}
} //fin main
} //fin class
Como paradigma de computación distribuida, los agentes móviles son radicalmente
diferentes al resto de paradigmas que se han visto. En otros paradigmas, procesos
independientes colaboran intercambiando datos sobre sus enlaces de red. Con los
agentes móviles, un proceso se transmite, llevando consigo los datos a compartir y
visitando la lista de procesos de su itinerario. La Figura 12.13 muestra esta
característica discriminatoria.
FIGURA 12.13: Contraste entre el paradigma de agentes móviles y los paradigmas
convencionales.
Ventajas de los agentes móviles
El paradigma de agentes móviles proporciona las siguientes ventajas:
 Los agentes móviles permiten un uso eficiente y económico de los canales de
comunicación, que pueden ser de ancho de banda reducido, latencia elevada, y
pudiendo ser proclives a errores. En contra, los paradigmas convencionales
requieren el intercambio repetido de paquetes de datos sobre la red. Si esto
afecta a grandes volúmenes de datos, el consumo de ancho de banda puede ser
considerable, con el consecuente retardo en el tiempo de respuesta o la
latencia. Por medio de agentes móviles, un único objeto se serializa y se
transmite por la red, potencialmente reduciendo el consumo de ancho de
banda. Además, ya que un agente móvil sólo se necesita transportar entre dos
nodos una vez, la probabilidad de fallo debido a un error de comunicación se
reduce. Por estas dos razones, los agentes móviles son especialmente
interesantes para enlaces de red inalámbricos.
 Los agentes móviles permiten el uso de dispositivos de comunicación
portátiles y de bajo coste para realizar tareas complejas incluso cuando el
dispositivo está desconectado de la red. Un agente se puede lanzar desde
cualquier dispositivo que soporte la arquitectura necesaria. Una vez lanzado, el
agente se desacopla de su origen y es capaz de realizar las tareas de forma
independiente de su dispositivo inicial. Con una implementación apropiada, un
agente móvil puede tener la inteligencia de saltarse nodos que fallen o de
buscar refugio momentáneo en nodos fiables.
 Los agentes móviles permiten operaciones asíncronas y una verdadera
descentralización. La ejecución de un agente móvil está desacoplada de su
servidor original y de los servidores participantes. Las tareas se realizan en
cada uno de los nodos individuales de una manera asíncrona, y no resulta
necesario que ninguno de los participantes asuma el papel de coordinador.
A pesar de las ventajas ofrecidas por los agentes móviles, el paradigma no se ha
desarrollado de forma amplia en aplicaciones industriales o comerciales. Una de las
principales pegas del paradigma es que puede suponer un riesgo de seguridad para los
participantes.
Existen consideraciones para ambos, servidores y agentes móviles. Desde el punto de
vista de los servidores que reciben un agente, agentes maliciosos o no autorizados
pueden hacer un uso fraudulento y destruir recursos locales. Sin restricciones, un
agente malicioso puede causar un caos en el servidor, de igual manera que lo hacen
los virus. Desde el punto de vista de un agente, servidores maliciosos pueden destruir
o alterar los datos del agente o su lógica. Por ejemplo, el itinerario de un agente móvil
se podría alterar o destruir por un servidor malicioso, de forma que el agente no
pudiese continuar con su viaje. O, los datos almacenados por el agente se podrían
alterar de forma que el agente se llevase información errónea.
La seguridad en sistemas de agentes es un área de investigación muy activa
[mole.informatik.uni-stuttgart.de, 9]. Algunas de las contramedidas que se han
propuesto son:
 Autenticación. Un agente debe autentificarse ante el servidor, y un servidor
de agentes debe autentificarse ante el agente.
 Cifrado. Un agente debe cifrar sus datos sensibles.
 Acceso a recursos. Un servidor forzará un estricto control de acceso a sus
recursos.
Sistemas basados en entornos para agentes móviles
Hay disponible un gran número de sistemas basados en entornos de desarrollo para
agentes móviles. Además de proporcionar la arquitectura para transportar agentes
móviles, estos sistemas también tratan cuestiones relativas a la seguridad, el soporte
transaccional, y la gestión de agentes. Los lectores que estén interesados en este tema
pueden buscar en referencias como [trl.ibm.com, 6], [concordiaagents.com, 7], y
[grasshopper.de, 8].
Servicios de red
En el paradigma de servicios de red [Edwards, 11], la red se ve como una
infraestructura para servicios, que “puede incluir aplicaciones, ficheros, bases de
datos, servidores, sistemas de información, y dispositivos, tales como
electrodomésticos móviles, almacenamiento o impresoras.” La Figura 12.14 ilustra
este paradigma. Una aplicación cliente puede utilizar uno o varios de estos servicios.
Los servicios se pueden añadir y eliminar de la red de forma autónoma, y los clientes
pueden localizar los servicios disponibles, a través de un servicio de directorio.
El protocolo SOAP (Simple Object Access Protocol), que se vio en el Capítulo 11, se
basa en este paradigma. Jini, que es anterior a SOAP, es un conjunto de herramientas
basado en este paradigma.
FIGURA 12.14: El paradigma de servicios de red.
Las Figuras 12.15 y 12.16 muestran la sintaxis de la implementación de un proveedor
de servicios en Jini, que proporciona el método decirHola(). La Figura 12.17 muestra
la implementación de un cliente de dicho servicio. Nótese que Jini hace uso de RMI,
que ya se vio en los Capítulos 7 y 8.
FIGURA 12.15: InterfazServidorHola.java
1 // Interfaz para el ServidorHola
2
3 import java.rmi.*;
4
5 public interface InterfazServidorHola extends Remote {
6
public String decirHola() throws RemoteException;
7 }
FIGURA 12.16: ServidorHola.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// Un ejemplo de servidor Jini sencillo
// M. Liu, basado en el ejemplo "Noel's Nuggets" [cc.gatech.edu, 14]
import net.jini.core.entry.*;
import net.jini.core.lookup.*;
import net.jini.core.discovery.*;
import net.jini.lookup.entry.*;
import com.sun.jini.lookup.*;
import com.sun.jini.lease.*;
import java.io.*;
import java.rmi.*;
import java.rmi.server.*;
public class ServidorHola extends UnicastRemoteObject
implements InterfazServidorHola, ServiceIDListener {
public ServidorHola () throws RemoteException {
super();
}
public String decirHola () throws RemoteException {
return ("¡Hola Mundo!");
}
// Este método está a la escucha de ServiceID de parte del
// servicio de directorio, cuando el ID esté disponible.
public void serviceIDNotify (ServiceID id) {
System.out.println (" ServiceID recibido: " + id);
}
public static void main (String[] args){
ServidorHola servidor;
Entry[] atributos;
JoinManager manager;
try {
System.setSecurityManager
(new RMISecurityManager ());
// Crea los atributos como un vector de objetos
// Entry que describen este servicio, y
// se registra en el servicio de búsqueda vía
// el JoinManager. El ServiceID, cuando esté disponible,
// le será indicado por medio del listerner del ServiceID.
atributos = new Entry[1];
atributos[0] = new Name("ServidorHola");
servidor = new ServidorHola();
manager = new JoinManager (
servidor, atributos, servidor,
new LeaseRenewalManager()
);
}
catch (Exception ex) {
ex.printStackTrace( );
}
} //fin main
} //fin class
FIGURA 12.17: Cliente Jini
1
2
3
4
5
// Un ejemplo de un cliente Jini
// M. Liu, basado en el ejemplo "Noel's Nuggets" [cc.gatech.edu, 14]
import net.jini.core.entry.*;
import net.jini.core.lookup.*;
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import
import
import
import
net.jini.core.discovery.*;
net.jini.lookup.entry.*;
com.sun.jini.lookup.*;
java.rmi.*;
class ClienteHola{
public static void main (String[] args){
Entry[] atributos;
LookupLocator buscador;
ServiceID id;
ServiceRegistrar registrar;
ServiceTemplate plantilla;
InterfazServidorHola servidorHola;
try {
System.setSecurityManager
(new RMISecurityManager ());
// Localizar el servcio de búsqueda de Jini
buscador = new LookupLocator("jini://localhost");
// Buscar el ServiceRegistrar
registrar = buscador.getRegistrar();
// Búsqueda del servicio
atributos = new Entry[1];
atributos[0] = new Name ("ServidorHola");
plantilla = new ServiceTemplate
(null, null, atributos);
servidorHola = (InterfazServidorHola)
registrar.buscador(plantilla);
// Invocar el método del servicio
System.out.println(servidorHola.decirHola());
}
catch (Exception ex) {
ex.printStaceTrace( );
}
}
}
La introducción que se ha presentado apenas toca los aspectos fundamentales de Jini y
no hace justicia a las sofisticadas capacidades proporcionadas por este conjunto de
herramientas. Un concepto interesante en Jini es el uso de “alquileres” (“leases”)
(línea 49 en la Figura 12.16). En un sistema Jini, cada servicio se asocia a un gestor
de renovación de alquileres. Cuando un cliente localiza un servicio Jini a través de
un servicio de búsqueda, el propio servicio de búsqueda actúa como elemento que
concede periodos de alquiler para el servicio. El cliente puede realizar peticiones
mientras que su alquiler no haya expirado. El uso de alquileres permite al sistema
proporcionar tolerancia a fallos de una forma más eficiente. (Los fallos en sistemas
distribuidos y la tolerancia a fallos se presentaron en el Capítulo 1.)
Espacios de objetos
Esta sección muestra el paradigma que proporciona el mayor nivel de abstracción: los
espacios de objetos. El paradigma de espacios de objetos tiene su origen en el
Espacio de Tuplas de Linda (Linda Tuplespace) desarrollado por David Gelernter
[Ahuja, Carrier, y Gelernter, 17] y es la base de los sistemas de Pizarras en el campo
de la Inteligencia Artificial [Corkill, 15]. En el paradigma de espacios de objetos, un
espacio es un repositorio para objetos, compartido y accesible por red. En lugar de
comunicarse entre sí, los procesos se coordinan intercambiando objetos a través de
uno o varios espacios. La Figura 12.18 ilustra este concepto. Los procesos interactúan
compartiendo los datos de estado en uno o más objetos o actualizando el estado de los
objetos según sus necesidades.
FIGURE 12.18: El paradigma de espacio de objetos.
Un proceso puede depositar un objeto en un espacio. A diferencia de los modelos de
mensajes, los procesos no modifican los objetos en el espacio ni invocan los métodos
de los objetos directamente. Un proceso que desea acceder a un objeto utilizará un
servicio de directorio para localizar el objeto en el espacio. Para modificar el objeto,
un proceso debe retirarlo explícitamente, actualizarlo y reinsertarlo en el espacio.
El paradigma de espacios de objetos es una área activa de investigación. Para poder
experimentar con este paradigma existe un conjunto de herramientas basado en Java,
JavaSpaces, que proporciona un entorno de trabajo para espacios de objetos.
En el API de JavaSpaces, se proporciona una interfaz llamada Entry. Un objeto Entry
puede escribirse o leerse del espacio. De la Figura 12.19 a la 12.21 se muestra un
programa de ejemplo sencillo que utiliza un objeto Entry que contiene un mensaje
“¡Hola Mundo!” y un contador. El servidor crea el objeto Entry y lo escribe en el
espacio de objetos por defecto. El cliente lee (toma) el objeto del espacio e incrementa
el contador, antes de escribirlo de nuevo en el espacio. Nótese que JavaSpaces utiliza
el API de Jini presentada en la sección 12.3.
FIGURA 12.19: Un ejemplo de una clase Entry de JavaSpaces.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Una clase Entry de ejemplo para un objeto de espacio JavaSpaces
// M. Liu, basado en el ejemplo proporcionado en:
// JAVASPACES PRINCIPLES, PATTERNS, AND PRACTICE [18]
import net.jini.core.entry.Entry;
public class ObjetoDeEspacio implements Entry {
public String mensaje;
public Integer contador; //Es necesario que sea un objeto
public ObjetoDeEspacio( ) {
}
public ObjetoDeEspacio(String mensaje) {
this.mensaje = mensaje;
contador = 0;
}
public String toString( ) {
return mensaje + " leido " + contador + " veces.";
}
public void incremento( ) {
contador = new Integer(contador.intValue() + 1);
}
} //fin class
FIGURA 12.20: Un programa de ejemplo que inicializa un objeto JavaSpaces.
1 // Un programa que inicializa un Entry de JavaSpaces.
2 // M. Liu, basado en el ejemplo proporcionado en:
3 // JAVASPACES PRINCIPLES, PATTERNS, AND PRACTICE [18]
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import net.jini.core.lease.Lease;
import net.jini.space.JavaSpace;
public class HolaMundo {
public static void main(String[] args) {
try {
SpaceObject mens = new SpaceObject("¡Hola Mundo!");
JavaSpace espacio;
espacio = (JavaSpace)space();
espacio.write(mens, null, Lease.FOREVER);
SpaceObject plantilla = new SpaceObject();
while (true) {
SpaceObject resultado = (SpaceObject)
espacio.read(plantilla, null, Long.MAX_VALUE);
System.out.println(resultado);
Thread.sleep(1000);
} //fin while
}
catch (Exception ex) {
ex.printStackTrace();
}
}
} //fin class
FIGURA 12.21: Un ejemplo de un cliente JavaSpaces.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Un programa cliente que accede a un Entry de JavaSpaces
// M. Liu, basado en el ejemplo proporcionado en:
// JAVASPACES PRINCIPLES, PATTERNS, AND PRACTICE [18]
import net.jini.core.lease.Lease;
import net.jini.space.JavaSpace;
public class ClienteHolaMundo {
public static void main(String[] args) {
try {
JavaSpace espacio = (JavaSpace)space();
SpaceObject plantilla = new SpaceObject();
// Retira el objeto del espacio repetidas veces,
// lo modifica, y lo deposita de nuevo en el espacio
while (true) {
// Lee el objeto del espacio
SpaceObject result = (SpaceObject)
espacio.take(plantilla, null, Long.MAX_VALUE);
result.incremento();
// Escribe el objeto en el espacio
espacio.write(result, null, Lease.FOREVER);
Thread.sleep(1000);
}//fin while
}
catch (Exception ex) {
ex.printStackTrace();
}
}
} //fin class
Es especialmente interesante que la exclusión mutua es una característica interna de
diseño del paradigma de espacios de objetos, ya que un objeto compartido sólo puede
ser accedido por un participante a la vez. La referencia [Ahuja, Carrier, y Gelernter,
17] proporciona excelentes ejemplos que ilustran las aplicaciones que se pueden
construir usando este paradigma.
A los lectores interesados en JavaSpaces se les recomienda consultar las referencias
[java.sun.com, 18], [jiniworld.net, 19], [onjava.com, 20], y [Alter, 23].
Tendencias futuras
Este capítulo ha presentado un gran número de paradigmas avanzados de
computación distribuida, muchos de los cuales se encuadran dentro del área de
investigación. Existen verdaderamente más paradigmas y herramientas que irán
surgiendo. Por ejemplo, peer-to-peer es un paradigma que recientemente ha recibido
mucha atención; se han desarrollado varios sistemas y API para dar soporte a este
paradigma, incluyendo el proyecto JXTA [jxta.org, 16]. Otro paradigma,
computación colaborativa, usa el concepto de canales para permitir que procesos
independientes colaboren en tiempo real; el entorno JSDT (Java Shared Data Toolkit)
[java.sun.com, 21] se puede utilizar “para crear aplicaciones de red, como pizarras
compartidas o entornos de chat. También se puede utilizar para hacer presentaciones
remotas, simulaciones compartidas, y distribuir fácilmente datos para trabajos en
grupo.”
Se espera que usted, como lector del libro, haya adquirido los conceptos básicos y
comprensión que le permitirá explorar paradigmas nuevos con los que no esté
familiarizado así como nuevas API de computación distribuida.
Resumen
Este capítulo ha proporcionado una visión general de los siguientes paradigmas
avanzados de computación distribuida:
 El paradigma de Sistemas de Colas de Mensajes, que proporciona emisión y
recepción de mensajes de forma asíncrona a través del uso de colas de
mensajes. Un entorno que da soporte a este paradigma es Java Message
System (JMS).
 El paradigma de agentes móviles, que da soporte al uso de programas
transportables. A pesar de que los agentes móviles se pueden implementar
directamente usando RMI, se recomienda el uso de entornos como Aglet,
Concordia, y Grasshopper.
 El paradigma de servicios de red, el cual muestra la red como una federación
de proveedores de servicios y de consumidores de los mismos. Una aplicación
puede consumir uno o más recursos, según lo requiera. El protocolo SOAP
(Simple Object Access Protocol) se utiliza para este paradigma. Jini de Java es
un conjunto de herramientas muy sofisticado que hace uso de un concepto
interesante que son los alquileres de servicios.
 El paradigma de espacios de objetos, el cual proporciona espacios lógicos
donde los objetos pueden depositarse y retirarse por elementos colaboradores.
JavaSpaces es un conjunto de herramientas que soportan este paradigma.
Hay otros paradigmas y otras tecnologías que no se han cubierto, incluyendo peer-topeer y computación colaborativa.
Ejercicios
1. Siga las instrucciones de [java.sun.com, 1] para instalar JMS (Java Message
System) en su ordenador.
a. Experimente con el ejemplo HolaMundo mostrado en las Figuras 12.4
y 12.5.
 Compile los ficheros fuente
 Arranque un receptor, luego un emisor. Describa y explique el
comportamiento.
 Arranque dos receptores, luego un emisor. Describa y explique el
comportamiento.
b. Repita parte del experimento con el ejemplo punto-a-punto
proporcionado en [java.sun.com, 1].
c. Repita parte del experimento con el ejemplo publicación/suscripción
proporcionado en [java.sun.com, 1].
2. Describa una aplicación que use una o más colas de mensajes punto-a-punto.
Explique cómo la aplicación saca partido del uso de cola(s) de mensajes en
términos de facilidad de implementación.
3. Describa una aplicación que use una o más colas de mensajes
publicación/suscripción. Explique cómo la aplicación saca partido del uso de
cola(s) de mensajes en términos de facilidad de implementación.
4. Siga las instrucciones del fichero README de la carpeta de ejemplos de
agentes móviles para ejecutar la demo de agentes móviles mostrada en las
Figuras de la 12.8 a las 12.12. Describa y explique el comportamiento.
5. Investigue el entorno de trabajo Aglets [trl.ibm.com, 6], un entorno para
agentes móviles.
a. ¿Cómo se proporciona transporte de código dentro del entorno Aglet?
b. ¿Qué otros servicios proporciona el entorno Aglet además del de
transporte de código?
c. Descargue e instale el paquete, experimente con los ejemplos
proporcionados.
6. Considere las siguientes aplicaciones listadas a continuación. Describa cómo
cada uno de estos paradigmas (sistemas de colas de mensajes, agentes móviles
y espacios de objetos) pueden aplicarse para desarrollar cada aplicación.
Nótese que no se le pide que realice la implementación. Su descripción debe
enmarcarse en términos del paradigma genérico, no de una API específica:
Las aplicaciones a considerar son:
a. Monitorización de la carga de mercancías a transportar por un vehículo
en camino entre almacenes y tiendas.
b. Una sala de chat.
c. Una subasta on-line.
d. Un servicio que permita a su universidad proporcionar información de
los cursos a los estudiantes. La información se actualiza
frecuentemente.
7. Investigue sobre JXTA [jxta.org, 16] y escriba un informe del soporte para el
paradigma peer-to-peer. Incluya en su informe una descripción de la
arquitectura, del API, y programas de ejemplo. ¿Dónde pondría este
paradigma dentro de la jerarquía de paradigmas distribuidos?
8. Investigue sobre JSDT (Java Shared Data Toolkit) [pandonia.canberra.edu.au,
22] y escriba un informe sobre el paradigma al que da soporte. Incluya en su
informe una descripción de la arquitectura, del API, y programas de ejemplo.
¿Dónde pondría este paradigma dentro de la jerarquía de paradigmas
distribuidos?
Referencias
1. Java Message Service Tutorial, http://java.sun.com/products/jms/tutorial/
2. Microsoft MSMQ Home Page, http://www.microsoft.com/msmq/default.htm
3. IBM’s MQ-Series, http://www-4.ibm.com/software/ts/mqseries/
4. Java™ 2 Platform, Enterprise Edition, http://java.sun.com/j2ee/
5. D. Lange y M. Oshima. “Seven Good Reasons for Mobile Agents.” Communications of the ACM, March 1999.
6. IBM Aglet. http://www.trl.ibm.com/aglets/
7. Concordia. http://www.concordiaagents.com/
8. Grasshopper 2, http://www.grasshopper.de/index.html
9. Security in mobile agent systems, http://mole.informatik.uni-stuttgart.de/security.html
10. Jini™ Network Technology, http://www.sun.com/jini/
11. Keith Edwards. Core Jini. Upper Saddle River, NJ: Prentice Hall PTR, 2000.
12. Jan Newmarch’s Guide to JINI Technologies, http://jan.netcomp.monash.edu.au/java/jini/tutorial/Jini.xml
13. Jini Planet, http://www.kedwards.com/jini/
14. Noel’s Nuggets, http://www.cc.gatech.edu/~kris/cs7470/nuggets/: Jini tutorial, with examples and instructions.
15. Daniel D. Corkill. “Blackboard Systems.” AI Expert 6, no. 9 (September 1991): 40–47.
16. Project JXTA, http://www.jxta.org/
17. Sudhir Ahuja, Nicholas Carriero, and David Gelernter. “Linda and Friends.” Computer, August 1986: 26–34.
18. Eric Freeman, Susanne Jupfer, y Ken Arnold. JavaSpaces: Principles, Patterns, and Practice. Reading, MA:
Addison-Wesley, 1999. http://java.sun.com/docs/books/jini/javaspaces/
19. The Nuts and Bolts of Compiling and Running JavaSpaces Programs,
http://www.jiniworld.net/document/javaspace/The Nuts and Bolts of Compiling and Running JavaSpaces(TM).htm
Descargar