Invocación de Métodos Remotos - LDC

Anuncio
Invocación de Métodos Remotos
RMI: Remote Method Invocation
Prof. Wílmer Pereira
Universidad Simón Bolívar
Arquitectura Cliente/Servidor
Request
Cliente
Servidor
Reply
¿ Cómo permitir comunicación entre objetos situados
en diferentes máquinas ?
¿ Cómo llamar a métodos de programas que corren en
máquinas diferentes ?
La
Lainvocación
invocacióndel
delservicio
servicioremoto
remotoes
esaapartir
partirde
deun
unobjeto
objeto
(creado
(creadoen
enelelcliente)
cliente)que
quellama
llamaaaun
unmétodo
método
(implementado
(implementadoen
enelelservidor)
servidor)
La
Laidea
ideaes
estener
tenerun
uncontexto
contextode
deejecución
ejecuciónparecido
parecidoal
allocal
local
bajo
bajouna
unaarquitectura
arquitecturacliente/servidor
cliente/servidor
Llamadas a Métodos Remotos
El
Elcliente
clientenecesita
necesitahacer
hacertransparente
transparentelalallamada
llamada
aamétodos
métodosremotos
remotos=>
=>stubs
stubs
! El stub paquetiza los parámetros (marshalling) y los
codifica en un formato estándar independientes de los
procesadores involucrados en la aplicación cliente/servidor
Big-endian
! El stub da la impresión de localidad al cliente, asegurando
transparencia
! El servidor asegura:
•
•
•
•
desempaqueta los parámetros (unmarshalling),
llama al método invocado,
paquetiza los valores de retorno o excepción (marshalling)
envía información al cliente.
Principios de una llamada remota
Llamada al método remoto desde el cliente:
centralWarehouse.getQuantity(“SuperSucket 100”);
Interfaz común al cliente y servidor:
interface Warehouse {
public int getQuantity(String description)
throws RemoteException:
.
.
.
}
Declaración del objeto local:
Warehouse centralWarehouse = ...;
Carga dinámica de clases
El
Elcliente
clienterequiere
requierecargar
cargar
las
lasclases
clasesyyexcepciones
excepciones
que
queelelservidor
servidorcambie,
cambie,
según
segúnsu
suevolución
evolución
Carga dinámica con el
ClassLoader
Sin embargo ...
esto implica problemas de seguridad
En consecuencia ...
se necesita al security manager para impedir
llegada de virus a través de los stubs
Ejemplo: Interfaz e implantación
Interfaz compartida por el cliente y el servidor:
interface Product extends Remote {
public String getDescription()
throws RemoteException:
}
Llamada del cliente:
Product p;
String d=p.getDescription();
Implantación del método remoto:
public class ProductImpl extends UnicastRemoteException
implements Product {
public ProductImpl(String d)
throws RemoteException
{ descr=d; }
public String getDescription()
throws RemoteException
{ return “Esto es un”+descr; }
private String descr;
}
Jerarquía de clases
Object
Remote
RemoteObject
RemoteStub
RemoteServer
UnicastRemoteObject
SUN propone la clase MulticastRemote para manejar
objetos replicados en múltiples servidores
Convenciones RMI
Sufijos
Sin:
Interfaz común cliente/servidor (Product)
Impl:
Clase del servidor que implemente la interfaz (ProductImpl)
Server:
Clase que crea los objetos servidores (ProductServer)
Client:
Clase que llama a métodos remotos (ProductClient)
_Stub
Subclase generada automáticamente por rmic (Product_Stub)
rmic genera el stub que es usado por el cliente
rmic
rmic ProductImpl
ProductImpl
Servicio de registro de stubs
El
Elservidor
servidorcarga
cargalos
losstubs
stubspor
porcada
cadauno
unode
desus
susobjetos
objetos
(generado
(generadopor
porrmic)
rmic)para
paraque
quepueda
puedaser
ser
descargado
descargadopor
porcada
cadaobjeto
objetodel
delcliente
cliente
Carga el stub en servidor de registro (bind)
//servidor
ProductImpl pl = new ProductImpl();
Naming.bind(“toaster”,pl);
Descarga el stub del servidor de registro (lookup)
//cliente
Product p = (Product) Naming.lookup
(“rmic://www.ldc.usb.ve/toaster”);
! El puerto por defecto es el 1099
! La aplicación servidor debe correr en la misma máquina del
servidor de registro (por razones de seguridad)
Código de ejemplo (Servidor)
import java.rmi.*;
import java.rmi.server*;
public class ProductServer {
public static void main(String args[]) {
try {
ProductImpl p1 = new ProductImpl(“Black Toaster”);
ProductImpl p2 = new ProductImpl(“Express Oven”);
Naming.rebind(“toaster”,p1);
Naming.rebind(“oven”,p2);
} catch (Exception e) {
System.out.println(“Error: “+e);
}
}
}
! Antes de correr el servidor debe levantarse el servidor de registro
! El servidor queda levantado indefinidamente con un thread que
lanza el objeto de UnicastRemoteObject
Código de ejemplo (Implantación del
Servidor)
import java.rmi.*;
import java.rmi.server*;
public class ProductImpl extends UnicastRemoteObject
implements Product {
public ProductImpl(String n) throws RemoteException
{ name = n; }
public String getDescription() throws RemoteException
{ return “Est es un “+name; }
private String name;
}
! A partir de esta clase se crean los stubs que deben cargarse en el
servidor de registro (bind) y ser bajados por el cliente (lookup)
! Los métodos que llama el cliente están implantados en esta clase
Código de ejemplo (Interfaz)
import java.rmi.*;
public interface Product extends Remote {
String getDescription() throws RemoteException;
}
! La interfaz debe estar tanto en el servidor como en el cliente de la
aplicación
! Inicialmente se instala el servidor de registro
rmiregistry
rmiregistry &&
! Se ejecuta el servidor de la aplicación para cargar los stubs en el
servidor de registro que fue instalado antes
java
java ProductServer
ProductServer
Codigo de ejemplo (Cliente)
import java.rmi.*;
import java.rmi.server*;
public class ProductClient {
public static void main(String args[]) {
System.setSecurityManager(new RMISecurityMananger());
String url = “rmi://localhost/”
try {
Product c1 = (Product)Naming.lookup(url+”toaster”);
Product c2 = (Product)Naming.lookup(url+”oven”);
System.out.println(c1.getdescription());
System.out.println(c2.getdescription());
} catch (Exception e) {
System.out.println(“Error: “+e);
}
System.exit(0);
}
}
El programa instala el manejador de seguridad y se baja los stubs
(uno por cada objeto del cliente) para poder llamar al método remoto
Políticas de seguridad de la
aplicación
El
Elmanejador
manejadorde
deseguridad
seguridadrestringe
restringeaacualquier
cualquier
Código
Códigode
deser
sercargado
cargadodesde
desdeelelcliente
cliente
Sin embargo el cliente necesita conexión para:
! Bajar los stubs del servidor de registro
! Acceder a los objetos remotos para llamar a los métodos remotos
En consecuencia se debe suplir un archivo de seguridad:
cliente.policy
grant {
permission java.net.SocketPermission “*:1024-65535”,”connect”;
};
java
java ProductClient
ProductClient -Djava.security.policy=client.policy
-Djava.security.policy=client.policy
Correr la aplicación (localmente)
! Compilar fuentes en el servidor
javac Product*.java
! Correr rmic para generar los stubs
rmic ProductImpl
! Instalar el servidor de registro
rmiregistry &
! Instalar el servidor
java ProductServer &
! Correr el cliente
java –Djava.security.policy=cliente.policy ProductClient
Directorios y archivos
Servidor
Cliente
ProductServer.class
ProductClient.class
ProductImpl.class
Product.class
Product.class
client.policy
ProductImpl_Stub.class
Download
ProductImpl_Stub.class
Product.class
Correr la aplicación (remotamente)
Para bajar los stubs debe haber un servidor Web
corriendo en el servidor
! Se puede instalar un servidor Web sencillo desde
ftp://java.sun.com/pub/jdk1.1/rmi/class-server.zip
! Mover el directorio download al directorio del servidor
Web
! Cambiar el client.policy para conectarse al servidor
de registro, implantaciones del servidor y el puerto del
HTTP. Todo esto indicando la máquina remota
grant {
permission java.net.SocketPermission
“servok.ldc.usb.ve:1024-65535”,”connect”;
permission java.net.SocketPermission
“servok.ldc.usb.ve:80”,”connect”;
};
Aplicación con servidor Web
! Levantar el rmiregistry en un shell sin classpath y
desde un directorio sin .class
! Desde un shell levantar el servidor dando el URL del directorio
download
java
javaProductServer
ProductServer–Djava.rmi.server.codebase=http://localhost/download/
–Djava.rmi.server.codebase=http://localhost/download/
! Modificar el URL en el cliente para poder acceder al servidor
remoto
String url = “rmi://servok.ldc.usb.ve/”
Product cl= (Product)Naming.lookup(url+”tostador”);
! Correr el cliente indicando las nuevas políticas de seguridad
java
javaProductClient
ProductClient–Djava.security.policy=client.policy
–Djava.security.policy=client.policy
Observaciones del enfoque RMI
! Este enfoque permite ejecutar concurrente el mismo método por varios
clientes. Sin embargo si se requiere exclusión mutua, sobre el método,
se puede utilizar la primitiva syncronize.
! No se tiene acceso a los mismos descriptores de I/O entre el cliente y
el servidor.
! Los stubs se encargan de los parámetros y lo único no permitido en los
métodos remotos, es el pasaje de parámetros por referencia. La única
condición es que los objetos pasados como parámetros deben
implementar la interfaz Serializable.
! No se pueden sobrescribir los métodos equals, clone y paint.
Deben escribirse métodos propios para realizar dichas tareas.
! Cuando se implementan la aplicación sobre applets, no se puede
modificar las restricciones de seguridad que impone el browser.
! Es conveniente usar levantar el servidor de registro (rmiregistry)
desde el servidor para evitar su proliferación en varias máquinas. El
comando es:
LocateRegistry.createRegistry(port);
Descargar