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.