Download Presentación RMI-2

Document related concepts
no text concepts found
Transcript
CONTENIDO
RMI
AVANZADO
• Carga dinamica de stubs
• Callbacks
Carga dinámica de Stubs
• Para tener acceso a un objeto remoto mediante RMI, el
cliente debe recibir un stub serializado y deserializarlo.
• El stub serializado contiene una referencia remota. La
referencia incluye datos como:
– Nombre del servidor donde se encuentra el objeto
remoto.
– Número de puerto en el servidor, en el que el
servicio RMI se encuentra escuchando en espera de
las invocaciones remotas.
• Los objetos serializados no contienen los métodos de la
clase. Para deserializarlos es necesario tener la
definición de la clase o bien alguna manera de
obtenerla.
Serialización
• Durante el proceso de serialización se almacenan
únicamente los datos del objeto original.
• No se almacena ninguna representación de los
métodos de la clase a la que pertenece el objeto.
• Cuando un objeto se deserializa, el cliente que lo recibe
debe tener manera de cargar el archivo que contiene la
información sobre los métodos (.class)
• De no ser posible localizar la clase, la deserialization
falla y aparecen las excepciones:
java.rmi.UnmarshalException
java.lang.ClassNotFoundException.
Obteniendo la clases
Carga dinámica de clases
•
Hay al menos 2 maneras de obtener las clases de los stubs.
•
La manera mas simple es copiar manualmente los archivos .class
en la computadora del cliente, colocándolos en el mismo directorio
del cliente ó en cualquier directorio del CLASSPATH.
– Esta manera es segura, confiable y fácil de entender. Es la
mejor manera de experimentar inicialmente con RMI
•
Eventualmente se llega a la conclusión de que este enfoque es
muy limitante y poco orientado a objetos. El cliente se hace
dependiente de la implementación del servicio y no únicamente de
su interfaz. Si se remplaza la clase servidora, será necesario
cargar manualmente un nuevo .class.
Carga dinámica de clases (cont …)
Stub serializado y anotado con el URL:
http://miServidor/carpeta/
Instancia del
Objeto remoto
(miServant)
Cliente
Servidor
URL
Descarga del archivo
miServant_Stub.class
Servidor
Web
carpeta/miServant_Stub.class
miServidor
• Un enfoque mas general es publicar mediante un
servidor de Web los archivos .class que vayan a
necesitar los clientes.
• Los objetos serializados pueden ser anotados con el
URL que permite localizar y descargar los .class de los
stubs mediante el servidor de Web.
• Cuando se deserializa el objeto, la máquina virtual java
del cliente (JVM) se conecta con el servidor de Web y
descarga automáticamente el archivo .class de manera
totalmente transparente para el cliente..
La propiedad java.rmi.server.codebase
• Se requiere una manera de anotar los stubs con el URL
apropiado. Esto se puede lograr asignando el valor del
URL al entorno de la JVM modificando la propiedad
llamada java.rmi.server.codebase en la JVM donde se
origina el stub (ó cualquier objeto serializado en
general).
• Al serializar un objeto, el valor de la propiedad codebase
se agrega entre los datos contenidos en el objeto
serializado.
Ejemplo
Security Managers
• Ejemplo:
java –Djava.rmi.server.codebase=http://cs.mty.itesm.mx/clases HelloServer
• El URL será agregado a los objetos que sean serializados
por el programa HelloServer.
• Cuando un objeto sea deserializado en otra JVM y no se
encuentre el archivo .class apropiado, este será
automáticamente descargado del directorio clases del
servidor cs.
• La descarga de código dinámico en una JVM
exige la instalación de un controlador de
seguridad (security manager). Esto implica
también definir una política de seguridad
mediante un archivo policy.
Instalando el Security Manager
Política de seguridad
•
•
La política mas simple de seguridad es la siguiente:
Para autorizar la carga dinámica, se debe incluir en el programa la
instrucción:
grant {
permission java.security.AllPermission;
System.setSecurityManager(new RMISecurityManager()) ;
};
•
Debe también definirse la propiedad java.security.policy. Esta
propiedad se configura con el nombre del archivo que contiene la
política de seguridad.
•
Esta política permite al código descargado hacer cualquier cosa a la
que el usuario tenga derecho.
•
Por ejemplo, leer, escribir y borrar cualquier archivo; abrir, leer y escribir
a cualquier socket; ejecutar cualquier comando del sistema operativo
del cliente, etc.
•
Utilícela solo con fines de prueba.
java –Djava.security.policy=policy.all HelloClient
La propiedad java.security.policy
•
Esta propiedad puede ser configurada desde la línea de comando al
ejecutar el cliente:
El registry y la carga dinámica de stubs
•
Si se utiliza carga dinámica de stubs, el comando rmiregistry debe
ejecutarse en un directorio en el que no pueda encuentrar el archivo
.class del stub (tampoco debe poder encontrarlo en el
CLASSPATH). Esto forza al registry a buscar la clase en el URL
(codebase) y anotar los stubs con esta dirección.
•
Cuando los clientes utilicen el servidor de nombres para localizar
los stubs estos ya traerán anotado el URL apropiado,
java –Djava.security.policy=policy.all HelloClient
•
O bién por programa utilizando el método:
System.setProperty(String key, String value)
Resumen de carga dinámica
Conclusión
• Utilizar carga dinámica de stubs en una aplicación RMI
implica:
– Instalar los archivos de clase de los stubs en un
directorio alcanzable por un servidor Web.
– Configurar la propiedad java.rmi.server.codebase en
el entorno del servidor RMI para que indique el URL del
directorio apropiado del servidor de Web.
– Crear un archivo de políticas de seguridad en el cliente.
– Configurar la propiedad java.security.policy en el
entorno del cliente.
– Crear un security manager en el cliente.
• La posibilidad de cargar dinámicamente los stubs tiene
mucha importancia por el posible impacto en la forma de
operar del sistema distribuido.
• El poder cambiar una clase por otra que implementa la
misma interfaz es el tipo mas importante de
polimorfismo de la programación orientada a objetos.
Introducción
• En el modelo cliente/servidor, el servidor es pasivo:
la interacción es iniciada por iniciativa del cliente, el
servidor espera la llegada de peticiones, las procesa
y genera la respuesta.
• Algunas aplicaciones requieren que el servidor inicie
la comunicación cada vez que ocurre algun evento.
Por ejemplo:
Callback en RMI
–
–
–
–
–
Polling vs. Callback
Callbacks en RMI
Si no se usa callback, un cliente tiene que comunicarse repetidamente
con un servidor pasivo (polling) si requiere ser notificado de la ocurrencia
de un evento en el servidor
Polling
Servidor
Monitores/alarmas
Juegos
Subastas
Mensajes
Groupware
• Cada cliente se registra a sí mismo en el servidor.
• El servidor llama a todos los clientes registrados cuando
ocurre un evento.
Callback
Servidor
Servidor
Clientes
C1
Lista de Clientes
...
Invocación remota
C2
Cliente
Cliente
El cliente invoca repetidamente
al servidor hasta que obtiene la
respuesta deseada
El cliente hace una invocación
para registrarse en el servidor y
espera a que el servidor le
llame (callback).
C3
Llamada del cliente
Callback
C4
C5
Archivos necesarios para callback
Interacciones durante el callback
Cliente
Servidor
1
Client.class
RMI
3
5
registry
2
SomeInterface_stub
_
3
Lista de Clientes
SomeInterface_Skel
3
CallbackInterface_Skel
SomeServer.class
5
4
5
Directorio del cliente
Directorio del servidor
Client.class
Server.class
ClientInterface.class
ServerInterface.class
ClientImpl.class
1.- El cliente busca la referencia remota del servidor en el registry.
2.- El registry regresa la referencia remota.
3.- Mediante el stub, el cliente invoca el método de registro del servidor y le pasa una
referencia de sí mismo.
4.- El servidor agrega la referencia en una lista.
5.- Cuando el evento de interés ocurre, el servidor hace una llamada (callback) a todos los
clientes registrados, invocando un método de la interfaz del cliente
Interfaz del Servidor
}
Máquina Servidor
ServerInterface.class
CallbackInterface_Stub
public interface HelloInterface extends Remote {
// remote method
public String sayHello() throws
java.rmi.RemoteException;
Máquina cliente
ClientInterface.class
ServerImpl.class
ServerImpl_ Stub.class
ClientImpl_Stub.class
ClientImpl_Skel.class
ServerImpl_Skel.class
Interfaz del Cliente para Callback
// an interface specifying a callback method
public interface HelloCallbackInterface extends
java.rmi.Remote
{
// method to be invoked by a client to add itself to the callback list
// method to be called by the server on callback
public void addCallback(
HelloCallbackInterface CallbackObject)
throws java.rmi.RemoteException;
public void callMe (String message)
throws java.rmi.RemoteException;
}
HelloServer, con callback
public class HelloServer extends UnicastRemoteObject implements
HelloInterface {
static int RMIPort;
// vector for store list of callback objects
private static Vector callbackObjects;
public HelloServer() throws RemoteException {
super();
callbackObjects = new Vector();
}
// method for client to call to add itself to its callback
public void addCallback( HelloCallbackInterface CallbackObject) {
// store the callback object into the vector
System.out.println("Server got an 'addCallback' call.");
callbackObjects.addElement (CallbackObject);
}
HelloServer, con callback - 2
public static void main(String args[]) {
…
Naming.rebind("hello", h);
…
callback( );
…
} // end main
private static void callback( ) {
…
for (int i = 0; i < callbackObjects.size(); i++) {
System.out.println("Now performing the "+ i +"th callback\n");
// convert the vector object to a callback object
HelloCallbackInterface client =
(HelloCallbackInterface) callbackObjects.elementAt(i);
…
client.callMe ( "Server calling back to client " + i);
…
HelloClient, con callback
public class HelloClient extends
UnicastRemoteObject implements
HelloCallbackInterface {
HelloClient() { // constructor
System.setSecurityManager(new
RMISecurityManager());
Stub
C
Servant C
Servant S
Stub
S
Cliente
Servidor
lookup
h = (HelloInterface)
Naming.lookup("hello");
h.addCallback(this);
} // d
t t
rebind
Registry
Caso de múltiples clientes a notificar
Resumen
Cliente
FASE DE
REGISTRO
Cliente
FASE DE
NOTIFICACION
Servidor
Cliente
Cliente
Resumen-2
• Callback:
– El cliente:
• Implementa una interfaz remota,
• Instancia un objeto,
• Pasa la referencia del objeto mediante la invocación de un
método del servidor.
– El servidor:
• Guarda las referencias de los clientes en una estructura.
• Cuando el evento esperado ocurre, el servidor invoca el
método callback de la interfaz del cliente para pasarle los
datos del evento al cliente.
• Callback:
– Callback es util en una aplicación en la que los
clientes desean ser notificados por el servidor cada
vez que ocurre un evento.
– El Callback en RMI se realiza pasando al servidor la
referencia del cliente.