Vous êtes sur la page 1sur 46

RMI : Remote Method Invocation

Appel de mthodes distance

Patrice Torguet torguet@irit.fr Universit Paul Sabatier

Plan du cours
l l l l l l l

Les RPC Architecture et fonctionnement de RMI Etapes de dveloppement et de mise en place Paramtres des mthodes Objets distants temporaires et ramasse miettes distribu Objet Activable Travaux pratiques

RPC : Remote Procedure Call


l l

Modle client/serveur Appel de procdures distance entre un client et un serveur


Le client appelle une procdure locale (souche stub ou proxy) La procdure locale utilise une connexion socket pour envoyer un identifiant de procdure et les paramtres au serveur Le serveur reoit la requte grce un socket, extrait lid de procdure et les paramtres (ceci est fait par un squelette skeletton) Le squelette excute la procdure et renvoie le rsultat via le socket Gnre la souche et le squelette partir dun fichier prsentant linterface des mthodes dans un format indpendant du langage (RPCL : RPC Language)

Outil rpcgen

RPC : Remote Procedure Call


l

Couche de prsentation XDR (eXternal Data Representation)


Format pivot de reprsentation des donnes de types primitifs et structurs (tableaux, tableaux de taille variable, structures) Indpendant de
l l l

Larchitecture (little endian/big endian) Le langage (ordre ligne/colonne dans les tableaux C et Fortran) Le systme (ASCII, EBCDIC)

Limitation :

Pas de gestion des concepts objets (encapsulation, hritage, polymorphisme) Pas de services volus : nommage RMI : mono langage, multi plateforme CORBA : multi langage, multi plateforme COM : multi langage, mono plateforme (multi pour DCOM) SOAP / .NET / web services : multi langage, multi plateforme

Successeurs :

Architecture et fonctionnement de RMI


l

RPC en Java

Invocation de mthodes sur des objets distribus Trs li au langage => simple mettre en uvre Gnration des souches/squelettes Service de nommage simple (prcise la machine dexcution) Activation

Outils

l l l l

Mono langage et multi plateforme : de JVM JVM Orient objet : utilisation de la srialisation Dynamique : tlchargement des classes des souches et des paramtres via HTTP (http://) ou NFS/SMB (file:/) Scuris : SecurityManager et fichier de scurit .policy

Architecture et fonctionnement de RMI

Objet Client

Objet Serveur

Stub Client

[Squelette]

Couche des Rfrences Distantes Couche Transport

Plus utilis depuis Java 2

Architecture et fonctionnement de RMI


5 rmiregistry doivent fonctionner sur la mme machine relle 3

Naming
4 5

Naming
2

Client
6

Serveur
1 6 6 1 6

Souche C.
JVM cliente

[Squel.]
JVM serveur

Architecture et fonctionnement de RMI


l

Fonctionnement ct serveur :

1) L'objet serveur est cr, si ncessaire il cre lobjet squelette (avant Java 2), puis le port de communication est ouvert 2) L'objet serveur s'enregistre auprs du service de noms RMI via la classe Naming de sa JVM (mthode bind ou rebind) 3) Le Naming enregistre le nom de lobjet serveur et une souche client (contenant l@IP et le port de comm.) dans le rmiregistry

Architecture et fonctionnement de RMI


l

Fonctionnement ct client :

4) L'objet client fait appel au Naming de sa JVM pour localiser l'objet serveur (mthode lookup) 5) Le Naming rcupre la souche client de l'objet serveur, 6) Le client appelle des mthodes de l'objet serveur au travers de la souche, qui cre un port de communication, et du squelette ventuel.

Etapes de dveloppement
1- Dfinition de l'interface de l'objet distant :

interface hritant de java.rmi.Remote mthodes : "throws java.rmi.RemoteException" paramtres de type simple, objets Srialisables (implements Serializable) ou Distants (implements Remote) classe hritant de java.rmi.server.UnicastRemoteObject et implmentant l'interface prcdente. crire un main permettant l'enregistrement auprs du Naming utilisation du Naming pour trouver l'objet distant appel(s) de mthodes

2- Ecrire une implmentation :


3- Ecriture d'un client


Etapes de dveloppement
l

Interface : Hello.java
public interface Hello extends java.rmi.Remote { String sayHello() throws java.rmi.RemoteException; }

Etapes de dveloppement
l

Implmentation de l'objet serveur : HelloImpl.java


import java.rmi.*; import java.rmi.server.UnicastRemoteObject; public class HelloImpl extends UnicastRemoteObject implements Hello { private String name; public HelloImpl(String s) throws RemoteException { super(); name = s; }

Etapes de dveloppement
l

Implmentation de l'objet serveur : HelloImpl.java


// Implmentation de la mthode distante public String sayHello() throws RemoteException { return "Hello from " + name; }

Etapes de dveloppement
l

Implmentation de l'objet serveur : HelloImpl.java


public static void main(String args[]) { // Cre et installe un gestionnaire de scurit // inutile si on ne tlcharge pas les classes des stubs et parametres // System.setSecurityManager(new RMISecurityManager()); try { HelloImpl obj = new HelloImpl("HelloServer"); Naming.rebind("HelloServer", obj); System.out.println("HelloServer dclar auprs du serveur de noms"); } catch (Exception e) { System.out.println("HelloImpl erreur : " + e.getMessage()); e.printStackTrace(); } }

Etapes de dveloppement
l

Implmentation de l'objet serveur : HelloImpl.java

Note : si on ne veut/peut pas faire driver la classe de lobjet serveur de UnicastRemoteObject on peut exporter lobjet avec la mthode UnicastRemoteObject.exportObject(objServeur); Il faudra gnrer la souche client avec rmic (y compris en Java 2) !

Etapes de dveloppement
l

Client : HelloClnt.java
import java.rmi.*; public class HelloClnt { public static void main(String args[]) { try { // Rcupration d'un proxy sur l'objet Hello obj = (Hello) Naming.lookup("//machine/HelloServer"); // Appel d'une mthode sur l'objet distant String message = obj.sayHello(); System.out.println(message); } catch (Exception e) { e.printStackTrace(); } }}

Mise en place
l l

Compilation des classes Gnration de la souche et du squelette (inutile pour une utilisation simple en Java 2)

Compilateur rmic : rmic HelloImpl Gnration de HelloImpl_Stub.class (Java 2) et HelloImpl_Skel.class (avant Java 2)

l l

Lancement du serveur de nom (rmiregistry) Note : on peut aussi appeler dans le main serveur

LocateRegistry.createRegistry(1099);

Mise en place
l

Mise en place de lobjet dimplmentation (simple)


Java 2 : java HelloImpl Avant : java -Djava.security.policy=java.policy HelloImpl

Contenu de java.policy
grant { permission java.net.SocketPermission "machclient:1024-65535", "connect,accept"; };

Mise en place
l

Mise en place de lobjet dimplmentation avec tlchargement de classe de paramtre


java -Djava.security.policy=java.policy ! -Djava.rmi.server.codebase=http://hostwww/myclasses/ HelloImpl

Contenu de java.policy
grant { permission java.net.SocketPermission "machclient:1024-65535", "connect,accept"; permission java.net.SocketPermission "hostwww:80", "connect"; };

Mise en place
l

Lancement du client

Simple : java HelloClnt Avec tlchargement de classes :


java HelloClnt -Djava.security.policy=./client.policy -Djava.rmi.server.codebase=http://hostwww/myclasses/ HelloClient

Contenu de client.policy
grant { permission java.net.SocketPermission "*:1024-65535", "connect"; permission java.net.SocketPermission "hostwww:80", "connect"; };

Paramtres des mthodes


l

Les paramtres et rsultats des mthodes distantes peuvent tre :


Des valeurs de types primitifs Des objets de classes implmentant linterface Serializable
l

Lobjet est srialis par la souche et envoy au squelette pour dsrialisation Cest la souche qui est srialise et envoye

Des objets de classes implmentant linterface Remote


l

Sinon exception : not serializable exception

Paramtres des mthodes


l l

Si la classe dun paramtre est inconnue du serveur (classe drive de la classe dun paramtre) : Lors de la dsrialisation, la JVM va tlcharger automatiquement le .class depuis le java.rmi.server.codebase

Objets distants temporaires et DGC


l

Passage dune souche en paramtre :

La souche correspond un objet dimplmentation enregistr auprs du rmiregistry (choix dun nom) Lobjet dimplmentation nest pas nomm et il nest utilis que pour la dure dune ou plusieurs invocations distantes Lobjet peut implmenter linterface java.rmi.server.Unreferenced pour tre prvenu lors de sa rcupration par le DGC

On utilise un objet distant temporaire


Objets distants temporaires et DGC


l

Interface Personne
public interface Personne extends Remote { public String getNom() throws RemoteException; public String getPrnom() throws RemoteException; }

Objets distants temporaires et DGC


l

Classe dimplmentation
public class PersonneImpl extends UnicastRemoteObject implements Personne, Unreferenced { private String nom; private String prnom; public PersonneImpl(String p, String n) throws RemoteException { super(); prnom = p; nom = n; } public String getNom() throws RemoteException { return nom; } public String getPrnom() throws RemoteException { return prnom; } public void unreferenced() { // utilis pour librer des ressources (threads, fichiers) } }

Objets distants temporaires et DGC


l

Retour sur Hello :


public interface Hello extends Remote { String sayHello(Personne p) throws RemoteException; }
public class HelloImpl extends UnicastRemoteObject implements Hello {
String sayHello(Personne p) throws RemoteException {

return "Hello "+p.getPrnom()+" "+p.getNom(); } }

Objets distants temporaires et DGC


l

Retour sur Hello :


public class HelloClnt { public static void main(String args[]) { try { Hello obj = (Hello) Naming.lookup("//machine/HelloServer"); for(int i=0; i < 1000; i++) { PersonneImpl p = new PersonneImpl("Albert", "Einstein"); String message = obj.sayHello(p); System.out.println(message); p = null; // force le GC local et le GC rparti } }

Ramasse miettes rparti (DGC)


l

client

Thread du main Cration de p

l serveur Thread de lobjet serveur Attente dinvocation de mthode Excution de sayHello(p) Appel de p.getPrnom() Appel de p.getNom() Envoi du rsultat

Thread de p Appel de sayHello(p) Attente mthode Excution de p.getPrnom() Excution de p.getNom() Excution de unreferenced Rception du rsultat

DGC

Attente dinvocation de mthode

Gestion des threads


l l

Attention : RMI peut utiliser plusieurs threads pour linvocation des mthodes. Il faut donc protger les attributs et autres ressources partages avec des synchronized

Traverse des pare-feu (RMI over HTTP)


l

RMI sait encapsuler ses requtes/rponses dans des messages HTTP POST en utilisant un proxy HTTP pour traverser un pare-feu 2 solutions

Soit le proxy HTTP dialogue directement avec le serveur RMI Soit le proxy HTTP dialogue avec un CGI qui dialogue avec le serveur RMI

Le fonctionnement est automatique : si un dialogue direct ne marche pas, RMI tente un passage par proxy HTTP

Traverse des pare-feu (RMI over HTTP)


l

Si on veut dsactiver ce mcanisme on peut lancer un client avec loption : -Djava.rmi.server.disableHttp=true Ct serveur, il faut que RMI puisse connatre le nom complet de la machine serveur. Si le systme ne le permet pas on peut le prciser manuellement en utilisant loption : -Djava.rmi.server.hostname=chatsubo.javasoft.com

Traverse des pare-feu (RMI over HTTP)


l

Pour utiliser la seconde solution il faut sur la machine serveur :


un serveur web sur le port 80 ; un script CGI mapp ainsi : /cgi-bin/java-rmi.cgi ce script doit :
l l

lancer java et une classe interne RMI qui appelle le serveur RMI mappe les variables CGI dans des variables pour java

il y a un exemple de ce script dans le JDK pour Solaris et Windows

Ce mcanisme est bien entendu beaucoup moins efficace que RMI sur TCP

Interoprabilit avec CORBA (RMI over IIOP)


l

l l

Si on veut utiliser RMI avec dautres langages que Java ou avec des applications compatibles CORBA on peut utiliser RMI over IIOP Au lieu de driver de UnicastRemoteObject on doit driver de javax.rmi.PortableRemoteObject Dans le main on doit remplacer Naming.bind par :
Context initialNamingContext = new InitialContext(); initialNamingContext.rebind("HelloServer", obj); // Context et InitialContext sont dans javax.naming

Interoprabilit avec CORBA (RMI over IIOP)


l

Ct client on fera :
Context ic = new InitialContext(); Object objref = ic.lookup("HelloServer"); // rfrence distante Hello hi = (Hello) PortableRemoteObject.narrow( objref, Hello.class); // trans-typage CORBA String message = hi.sayHello();

Pour gnrer les stubs/squelettes on utilise


rmic -iiop HelloImpl

Interoprabilit avec CORBA (RMI over IIOP)


l

Pour excuter il faut :


Lancer le serveur de noms
orbd -ORBInitialPort 1050&

Lancer le serveur
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1050 -classpath . HelloImpl

Lancer le client
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1050 -classpath . HelloClient

Interoprabilit avec CORBA (RMI over IIOP)


l

Pour linteroprabilit on doit gnrer un fichier IDL (Interface Definition Language) en faisant

rmic -idl HelloImpl

l l

Il est aussi possible dutiliser un POA (Portable Object Adapter) CORBA RMI over IIOP est utilis dans Java Enterprise Edition pour les EJB (Entreprise Java Beans) avec une interface Remote Cf cours de Master 2

Objet Activable
l

Principe du dmon inetd dUnix

Le dmon rmid dmarre une JVM qui sert lobjet dimplmentation uniquement au moment de linvocation dune mthode ( la demande) ou au dmarrage de la machine Package java.rmi.activation
l l

La classe dun objet activable doit driver de Activatable La classe doit dclarer un constructeur 2 args :
java.rmi.activation.ActivationId, java.rmi.MarshalledObject (paramtre de mise en place)

Objet Activable
l

Implmentation de l'objet serveur : HelloImpl.java


import java.rmi.*; import java.rmi.activation.*; public class HelloImpl extends Activatable implements Hello { private String name; public HelloImpl(ActivationID id, MarshalledObject o) throws RemoteException { super(id, 0); name = (String)o.get(); }

Objet Activable
l

Programme de mise en place


Donne linformation ncessaire lactivation rmid Enregistre le nom de lobjet auprs du rmiregistry ActivationDesc : description des informations ncessaires rmid Groupes dobjets activables
l l

rmid cre une JVM par groupe Les objets du mme groupe partagent la mme JVM
ActivationGroup : groupe dobjets activables ActivationGroupDesc : description du groupe ActivationGroupId : identifiant du groupe

Objet Activable
import java.rmi.*; import java.rmi.activation.*; import java.util.Properties; public class Setup { public static void main(String[] args) throws Exception { // fichier .policy qui sera utilis par la JVM active Properties props = new Properties(); props.put("java.security.policy", "/home/test/java.policy"); // Permet de prciser des paramtres la JVM et de choisir la JVM ActivationGroupDesc.CommandEnvironment ace = null; // Descripteur du groupe ActivationGroupDesc exampleGroup = new ActivationGroupDesc(props, ace); // Enregistrement du groupe ActivationGroupID agi = ActivationGroup.getSystem().registerGroup (exampleGroup);

Objet Activable
// Endroit o se trouve la classe de l objet activable String location = "file:/home/test/"; // Lobjet pass en paramtre du constructeur MarshalledObject data = new MarshalledObject(new String("serveur")); // Cration du descripteur de l objet ActivationDesc desc = new ActivationDesc (agi, "HelloImpl", location, data); // Enregistrement de l objet activable ; rcupration d une souche Hello obj = (Hello)Activatable.register(desc); // Enregistrement de la souche auprs du rmiregistry Naming.rebind("//machine/HelloServer", obj); System.exit(0);

}}

Objet Activable
l

Lancement :
lancer rmiregistry lancer rmid J-Djava.security.policy=java.policy lancer le programme de mise en place (Setup) Java Djava.security.policy=java.policy Djava.rmi.server.codebase=file:/home/test/ Setup lancer le client => rmid cre automatiquement la JVM + lobjet serveur

Exercices
l l

But du TD/TP : application rpartie permettant de grer des comptes bancaires. Un serveur grera tous les comptes bancaires et permettra des clients de se connecter et deffectuer les oprations suivantes :

void creer_compte(String id, double somme_initiale); void ajouter(String id, double somme); void retirer(String id, double somme); Position position(String id);

Exercices
l

crire linterface Banque, avec les mthodes :


l l l l

void creer_compte(String id, double somme_initiale); void ajouter(String id, double somme); void retirer(String id, double somme); Position position(String id);

Position est la classe suivante ( complter) :


public class Position { private double solde; private Date derniereOperation; public Position(double solde) { this.solde = solde; this.derniereOperation = new Date(); } }

Exercices
l

crire une interface Banque drivant de Remote qui dclare les mthodes distantes. crire la classe Compte qui permet de consulter la position dun compte, dajouter et de retirer une somme un compte. crire une classe BanqueImpl qui gre la partie serveur de notre application rpartie. Les comptes seront stocks dans une Hashtable qui permettra de retrouver un compte partir de son identification.

Exercices
l

crire une classe BanqueClient qui gre la partie client de notre application rpartie. Lapplication prsentera un petit menu (sous forme textuelle) permettant daccder aux diverses mthodes. On veut maintenant que le serveur, prvienne le client quand le solde de son compte devient ngatif ou infrieur une valeur choisie par le client.

Quel mcanisme, vu en cours, peut tre utilis ? Modifiez linterface et les classes pour grer cette situation.