Rappel des conclusions sur l’appel de procédure à distance

Page 1 sur 13Lecteur de document UniversityLib

Rappel des conclusions sur l’appel de procédure à distance

Java RMI, Distributed Computing, Object-Oriented Programming · course

Browse all programmation documents

Rappel des conclusions sur l’appel de procédure à distance

2

!! Avantages

!! Abstraction! ("les détails de la communication sont cachés!)"

!!

!! Outils de génération!: "facilitent la mise en œuvre

Intégration dans un langage! : "facilite la portabilité!, "mise au point

!! Limitations

!! La structure de l’application est statique

"! Pas de création dynamique de serveur

"! Pas de possibilité de redéploiement entre sites

!! Pas de passage des paramètres par référence

!! La communication est réduite à un schéma synchrone

!! La persistance des données n’est pas assurée

"!

Il faut la réaliser explicitement par sauvegarde des données dans des fichiers

JAVA RMI

[email protected]

!!

"Des mécanismes plus évolués visent à remédier à ces limitations

!!

"Objets répartis! ("ex! : "Java RMI!, "CORBA!) "pour les 2! "premières limitations

"Bus à messages! ("Message Oriented Middleware!)"

"Composants répartis! ("ex! : "EJB!, "Corba CCM!, ."Net!)"

!!

!!

Intérêt des objets pour la construction d’applications réparties

3

!! Encapsulation

!! L’interface (méthodes + arguments) est la seule voie d’accès

à l’état interne, non directement accessible

!! Classes et instances

!! Mécanismes de génération d’exemplaires conformes à un

même modèle

!! Héritage

!! Mécanisme de spécialisation : facilite la récupération et

réutilisation de l’existant

!! Polymorphisme

!! Mises en œuvre diverses des fonctions d’une interface

!! Facilite l’évolution et l’adaptation des applications

Extension du RPC aux objets (1)

4

!! Appel de procédure vs appel de méthode sur un objet

!! Exemple : insérer une entrée dans un annuaire

5

7

Extension du RPC aux objets (2)

!! Phase préalable : création d’instances d’une classe d’objets

!! Notion de fabrique (factory)

Notion de référence d’objet :

Contient tout ce qui est nécessaire pour atteindre l’objet distant

(Localisation, protocole d’accès)

Notion de référence

6

!! Référence : notion clé pour les objets répartis

!!

"Moyen d’accès à un objet distant,

!!

!! Son contenu ne peut pas être directement exploité «!opaque!»,

elle n’est utilisable que via un mécanisme d’appel à distance

"Contenu d’une référence

!!

"Toutes les informations nécessaires pour atteindre physiquement l’objet

"! Site de résidence (adresse IP)

"! Numéro de porte sur le site (Numéro de port)

"! Localisation interne au serveur

"!

!! Exemples! "!

"…

"En Java RMI! : "la référence est le talon client! ("stub!)"

!!

!! En Corba : format de référence spécifié! ("IOR! : "Interoperable Object Reference!)"

!!

"En DCOM! : "format! "“propriétaire”

Java RMI (Remote Method Invocation)

Java RMI : règles d’usage (1/2)

!! Motivation : construction d’applications réparties avec Java

!! Appel de méthode au lieu d’appel de procédure

!! Principe : même schéma que RPC

!! Le programmeur fournit

"! Une (ou plusieurs) description(s) d’interface

Ici pas d’IDL séparé : IDL=JAVA

"!

"! Le programme du serveur

"! Objets implémentant les interfaces

"! Serveur d’objets

"! Le programme du client

!! L’environnement Java fournit

!! Un générateur de talons : rmic

!! Un service de noms : Object Registry

voir http://java.sun.com/docs/books/tutorial/rmi/

8

!! Interface

!! L’interface d’un objet distant (Remote) est celle d’un objet

Java, avec quelques règles d’usage :

!! L’interface distante doit être publique

!! L’interface distante doit étendre l’interface java.rmi.Remote

!! Chaque méthode doit déclarer au moins l’exception

java.rmi.RemoteException

!! Passage d’objets en paramètre

!! Les objets locaux sont passés par valeur (copie) et doivent

être sérialisables (étendent l’interface java.io.Serializable)

!! Les objets distants sont passés par référence et sont

désignés par leur interface

Java RMI : règles d’usage (2/2)

Java RMI : règles d’écriture du serveur

9

10

!! Implémentation des classes distantes (Remote)

!! Une classe distante doit implémenter une interface elle-

même distante (Remote)

!! Une classe distante doit étendre la classe

java.rmi.server.UnicastRemoteObject (d’autres

possibilités existent)

!! Une classe distante peut aussi avoir des méthodes

Advertisement

appelables seulement localement (ne font pas partie

de son interface Remote)

!! Un serveur est une classe qui implémente l’interface

de l’objet distant

!! Spécifier les objets distants qui doivent être implémentées

!! Définir le constructeur de l’objet distant

!! Fournir l’implémentation des méthodes appelables à distance

!! Créer et installer le gestionnaire de sécurité

!! Créer au moins une instance de la classe serveur

!! Enregistrer au moins une instance dans le serveur de noms

Le compilateur IDL : rmic

11

!! Le compilateur rmic génère les amorces (stub/

skeleton)

!! assurent le rôle d’adaptateurs pour le transport des appels

distants.

!! réalisent les appels sur la couche réseau.

!! réalisent l’emballage/déballage des paramètres

(sérialisation ou marshalling/unmarshalling).

!! Une référence d’objets distant correspond à une

référence d’amorce (stub).

Stub/Skeleton

12

!! Stub (talon client)

!! Représentant local de l’objet distant.

!! Initie une connexion avec la JVM distante

!! Assemble les paramètres pour leur transfert à la JVM distante.

!! Attend les résultats de l’invocation distante.

!! Désassemble la valeur ou l’exception renvoyée.

!! Renvoie la valeur au client (l’appelant).

!! Skeleton (talon serveur)

!! Désassemble les paramètres pour la méthode distante.

!! Fait appel à la méthode demandée.

!! Assemble le résultat (valeur renvoyée ou exception) à destination

de l’appelant.

Serveur de noms : rmiregistry

Étapes d’un appel de méthode distante

13

15

!! Permet d’obtenir une référence d’objet distant

!! S’exécute sur chaque machine hébergeant des objets distants

!! Utilise par défaut le port 1099

!! Accepte comme opérations l'enregistrement, l'effacement et la

consultation (méthodes de la classe java.rmi.Naming)

!! void Naming.bind(String nom, Remote obj) : associe l'objet au nom

spécifié;

!! void Naming.rebind(String nom, Remote obj) : réassocie le nom au nouvel

objet;

!! void Naming.unbind(String nom) : supprime l'enregistrement

correspondant;

!! Remote Naming.lookup(String nom) : renvoie la référence (stub) de

l'objet enregistré sous le nom donné;

!! String[] Naming.list(String nom) : renvoie la liste des noms enregistrés.

Développer une application avec RMI

Exemple : Inversion d’une chaîne de caractères

16

17

1. Définir une interface distante (App.java).

2. Créer une classe implémentant cette interface (AppImpl.java).

3. Compiler cette classe (javac AppImpl.java).

4. Créer une application serveur (AppServer.java).

5. Compiler l’application serveur.

6. Créer les classes stub et skeleton à l’aide de rmic:

AppImpl_Stub.java et AppImpl_Skel.java

7. Démarrage du serveur de noms (registre) avec rmiregistry.

8. Lancer le serveur AppServer pour la création d’objets et leur

enregistrement dans rmiregistry.

9. Créer une classe cliente qui appelle des méthodes distantes de

l’objet distant (AppClient.java).

10. Compiler cette classe et la lancer.

!! Invocation distante de la méthode reverseString() d’un objet

distant qui inverse une chaîne de caractères fournie par

l’appelant.

!! Classes nécessaires:

!! ReverseInterface : interface qui décrit l’objet distant

!! Reverse : qui implémente l’objet distant

!! ReverseServer : le serveur d’objets RMI

!! ReverseClient : le client qui utilise l’objet distant

Interface

19

!! Interface de l’objet

!! Permet de décrire les différentes méthodes de l'objet distant

!! Partagée par le client et le serveur.

!! Doit étendre l’interface Remote définie dans java.rmi.

!! Toutes ses méthodes doivent déclarer l’exception

RemoteException.

!! RemoteException est déclenchée si :

!! connexion refusée à l’hôte distant

!! l’objet n’existe plus,

!! un problème d’assemblage ou de désassemblage.

Interface

20

!

import java.rmi.Remote;!

import java.rmi.RemoteException;!

public interface ReverseInterface extends Remote !

{!

}!

!String reverseString(String chaine) throws RemoteException;!

Implémentation de l’objet distant

Implémentation de l’objet distant

21

22

!! Une classe qui implémente l'interface définie

!! Permettre de rendre un objet accessible à distance par des

clients.

!! Doit permettre l’exposition de l'objet distant:

!! La solution (la plus simple) consiste à étendre la classe

UnicastRemoteObject de java.rmi.server.

import java.rmi.*;!

import java.rmi.server.*;!

public class Reverse extends UnicastRemoteObject implements ReverseInterface {!

public Reverse() throws RemoteException!

! {!

! super();!

Advertisement

}!

! public String reverseString (String ChaineOrigine) throws RemoteException !

! {!

! int longueur=ChaineOrigine.length();!

! StringBuffer temp=new StringBuffer(longueur);!

! for (int i=longueur; i>0; i--) !

! {!

!

! }!

! return temp.toString();!

!temp.append(ChaineOrigine.substring(i-1, i));!

}!

}!

Serveur d’objets

Serveur d’objets

23

24

Les opérations réalisées par le serveur:

1.! Définir un gestionnaire de sécurité : Objet de la classe

RMISecurityManager qui autorisera le chargement depuis une

autre application de classes sérialisables:

System.setSecurityManager (new RMISecurityManager());!

!

2.! Créer les objets distants par instanciation de classes

Remote:

MonObjetDistant Objet = new MonObjetDistant;!

3.! Exposer les objets distants : rendre accessibles dans le

serveur

!! Si la classe de l'objet a été définie comme une extension de

UnicastRemoteObject, l’exposition est automatique.

!! Sinon, l'objet doit être exposé explicitement par appel de la

méthode exportObject de la classe UnicastRemoteObject:

UnicastRemoteObject.exportObject(unObjet);!

!

4.! Faire connaitre l'existence des différents objets au serveur de

noms (rmiregistry) de la machine sur laquelle ce serveur

s'exécutera

Naming.rebind("nomUnObjet", unObjet);!

!

Serveur d’objets

25

import java.rmi.*;

public class ReverseServer {

public static void main(String[] args) {

!System.setSecurityManager(new RMISecurityManager());

try { System.out.println( "Serveur : Construction de l’implémentation ");

Reverse rev= new Reverse();

System.out.println("Objet Reverse lié dans le RMIregistry");

Naming.rebind("rmi://localhost:1099/MyReverse", rev);

System.out.println("Attente des invocations des clients ...");

}

catch (Exception e) {

System.out.println("Erreur de liaison de l’objet Reverse");

System.out.println(e.toString()) }

}}

Le client (1/3)

26

!! Le client récupère le stub de l'objet : il s'adresse au

serveur de noms auprès duquel l'objet a été enregistré.

!! Cette opération est réalisée en invoquant la méthode

lookup de la classe Naming.

!! Pour cela, il doit nommer complètement l'objet concerné

au travers d'une URL de la forme générale suivante :

rmi://machine:port/nom

!! Dans une telle URL,

"! si le nom de machine est omis, la machine locale est considérée;

"! si le numéro de port est omis, le numéro par défaut (1099) est

considéré.

Le client (2/3)

27

28

!! La méthode lookup est susceptible de provoquer une exception

RemoteException.

!! La récupération d'un stub par un client a la forme générale suivante:

try { !

!

!MonInterface stub= (MonInterface) Naming.lookup (adresse_de_l'objet);!

!} !

catch (Exception e){-------- }!

!

!! Une fois le stub est récupéré, un client peut invoquer sur ce stub des

méthodes de l'interface comme il ferait sur un objet local:

objet=stub.méthode(paramètres);

Le client (3/3)

import java.rmi.*;!

public class ReverseClient {!

!public static void main (String [] args) {!

! System.setSecurityManager(new RMISecurityManager());!

! try{!

!

!("rmi://localhost:1099/MyReverse");!

!ReverseInterface rev = (ReverseInterface) Naming.lookup

!

!String result = rev.reverseString (args [0]);!

!System.out.println ("L’inverse de "+args[0]+" est "+result);!

!

!

!

! }!

! catch (Exception e) {!

!

!

}}}!

!System.out.println ("Erreur d’accès à l’objet distant.");!

!System.out.println (e.toString());!

Gestionnaire de sécurité

Gestionnaire de sécurité

29

30

!! Installer un gestionnaire de sécurité

!! Permet de protéger la machine virtuelle java de tout

utilisateur malintentionné qui essaye de faire tourner du

code malicieux sur la machine.

!! Utiliser le gestionnaire de sécurité fournit par RMI:

RMISecurityManager

Advertisement

System.setSecurityManager(new RMISecurityManager());

!! La politique de sécurité spécifie les actions

autorisées, en particulier sur les sockets

!! Les opérations possibles sur les sockets:

!! connect est utilisé pour établir une connexion avec un

serveur.

!! listen est utilisé par un serveur pour indiquer qu'il est

disposé à accepter des connexions.

!! Après un listen, un serveur peut attendre une demande

de connexion d'un client par accept

Gestionnaire de sécurité

Fabrique d’objets (Factory)

31

32

!! Exécuter le programme java utilisant un gestionnaire de sécurité

avec l’option :

java –D java.security.policy=java.policy NomClasse

Où java.policy et le fichier des permissions

!! Exemple de contenu du fichier java.policy:

grant {

permission java.net.SocketPermission "localhost 1024-65535","connect,accept";

permission java.net.SocketPermission !":80", "connect";

};

!! Phase préalable : création d’instances d’une classe d’objets

!! Notion de fabrique (factory)

Notion de référence d’objet :

Contient tout ce qui est nécessaire pour atteindre l’objet distant

(Localisation, protocole d’accès)

Fabrique d’objets (Factory)

Fabrique d’objets (Factory)

33

!! Motivation

34

!! Permettre au client de construire des instances multiples d’une classe C sur le site

serveur

!! Le new n’est pas utilisable tel quel (car il ne gère que la mémoire locale, celle

du client)

!! Solution : appel d’un objet FabriqueC, qui crée localement (sur le serveur) les

instances de C (en utilisant new C)

!! Exemple

/Interface de l’objet distant/

public interface Annuaire extends Remote{

public boolean inserer(String nom, int id) throws RemoteException;

public boolean supprimer(String nom, int id) throws RemoteException;

public Info rechercher(String nom) throws RemoteException;

}

/Interface de fabrique d’objets/

public interface FabAnnuaire extends Remote{

public Annuaire newAnnuaire(String titre) throws RemoteException ;

}

/*L’implementation de l’objet distant

public class AnnuaireImpl implements Annuaire extends UnicastRemoteObject{

private String titre;

public Annuaire(String titre) {this.titre=titre};

public boolean inserer(String nom, Info info) throws RemoteException{…};

public boolean supprimer(String nom) throws RemoteException{…};

public Info rechercher(String nom) throws RemoteException{…};

}

/*L’implémentation de la fabrique d’objets

public class FabAnnuaireImpl implements FabAnnuaire extends UnicastRemoteObject{

public FabAnnuaireImpl{};

public Annuaire newAnnuaire(String titre) throws RemoteException {

return new AnnuaireImpl(titre)};

}

Fabrique d’objets (Factory)

Fabrique d’objets (Factory)

35

/Serveur d’objets/

import java.rmi.*;

public class Server {

public static void main (String [ ] argv) {

/ lancer SecurityManager /

System.setSecurityManager (new RMISecurityManager ()) ;

try {

Naming.rebind ("Fabrique”,new (FabAnnuaireImpl)) ;

System.out.println ("Serveur prêt.") ;

}

catch (Exception e) {

System.out.println("Erreur serveur : " + e) ;

}

}

}

36

/Code Client/

import java.rmi.*;

public class HelloClient {

public static void main (String [ ] argv) {

/ lancer SecurityManager /

System.setSecurityManager (new RMISecurityManager ()) ;

try {

/ trouver une référence vers la fabrique /

FabAbannuaire fabrique = (FabAbannuaire ) Naming.lookup ("rmi://goedel.imag.fr/Fabrique") ;

/ créer un annuaire /

annuaireIMAG = fabrique.newAnnuaire("IMAG");

/ créer un autre annuaire /

annuaireINRIA= fabrique.newAnnuaire("INRIA");

/ utiliser les annuaires /

annuaireIMAG.inserer(…, …);

annuaireINRIA.inserer(…, …);

….

} catch (Exception e) {

System.out.println("Erreur client : " + e) ;

}}}

Fonctionnement d’ensemble de la fabrique

Passage d’objets en paramètres

37

38

Deux cas possibles

!! Passage en paramètre d’un objet local (sur la JVM de l’objet appelant)

!! Passage par valeur : on transmet une copie de l’objet (plus précisément : une

copie de l’ensemble ses variables d’état)

!! Pour cela l’objet doit être sérialisable (i.e. implémenter l’interface

java.io.Serializable)

!! Exemple de l’annuaire : le client transmet un objet de la classe locale Info

!! Passage en paramètre d’un objet non-local (hors de la JVM de l’objet

Advertisement

appelant, par ex. sur un site distant)

!! Passage par référence : on transmet une référence sur l’objet (plus précisément :

un stub de l’objet). Le destinataire utilisera ce stub pour appeler les méthodes

de l’objet.

!! Exemple de l’annuaire : le client passe un objet de type Annuaire (localisé sur le

serveur distant)

Passage d’objets en paramètres

Passage d’objets en paramètres

39

40

!! Notions sur les objets sérialisables

!! Un objet sérialisable (transmissible par valeur hors de sa

JVM) doit implémenter java.io.Serializable

!! Les objets référencés dans un objet sérialisable doivent aussi

être sérialisables

!! Comment rendre effectivement un objet sérialisable ?

"! Pour les variables de types primitifs (int, boolean,..) rien à faire

"! Pour les objet dont les champs sont constitués de telles variables :

rien à faire

"! On peut éliminer une variable de la représentation sérialisée en

la déclarant transient

"! Pour un champ non immédiatement sérialisable (ex. : Array), il faut

fournir des méthodes readObject() et writeObject()

!! Voir javadoc de l’interface Serializable et des classes

ObjectOutputStream et ObjectInputStream

Fonctionnement interne de JavaRMI

Fonctionnement interne de javaRMI

41

!! La classe UnicastRemoteObject

!! Rappel de la règle d’usage: une classe d’objets accessibles à distance étend

la classe java.rmi.UnicastRemoteObject

"! La principale fonction de cette clase se manifeste lors de la création d’une instance

de l’objet

public class AnnuaireImpl extends UnicastRemoteObject! {"…!}"

AnnuaireImpl! ("…!) { /* "le constructeur d’AnnuaireImpl appelle automatiquement

! "le constructeur de la superclasse UnicastRemoteObject*/

monAnnuaire! = "new AnnuaireImpl! ("…!) ;"

"! Le constructeur de UnicastRemoteObject crée une instance de stub pour l’objet, en utilisant la

classe Annuaire_Stub engendrée par rmic, et retourne ce stub comme résultat de la création.

!! Le contenu d’un stub

!! Un stub contient essentiellement une variable ref de type RemoteRef qui contient la

localisation de l’objet (adresse IP, port)

!! Un appel de méthode se fait par appel de ref.invoke() qui utilise les sockets pour la

communication

42

!! Le serveur de noms (registry)

!! Classes utiles (fournies par java.rmi)

"! Naming : sert de représentant local du serveurs de noms

"! Permet d’utiliser les méthodes bind(), rebind(), lookup(), unbind(), list()

"! LocateRegistry: permet de localiser un serveur de noms

(rmiregistry) et éventuellement d’en créer un. En général invisible

au client (appelé en interne par Naming)

Appel en retour (callback)

Appel en retour : principe

43

!! Le problème

!! Réaliser un appel du serveur vers le client

!! Intérêt

!! Augmenter l’asynchronisme

"! appel client-serveur avec retour immédiat (demande service)

"! rappel serveur-client quand le service est exécuté

!! Augmenter le dynamisme

"! Le serveur peut demander des informations complémentaires au

client en cours d’exécution

"! L’exécution du service peut faire appel à des services fournis par

le client

"! Exemple : traitement d’exceptions

44

!! Le client passe en paramètre au serveur l’objet à rappeler

!! Le serveur exécute un appel asynchrone sur cet objet

Appel en retour : réalisation

(interfaces des objets distants)

45

46

Appel en retour : réalisation (le servant)

Appel en retour : réalisation (le serveur)

Appel en retour : réalisation (le callback)

47

48

Appel en retour : réalisation (un client)

49

Conclusion

50

!! Extension du RPC aux objets

!! Permet l’accès à des objets distants

!! Pas de langage séparé de description d’interfaces (IDL

fourni par Java)

!! Limitations

!! Environnement restreint à un langage unique (Java)

!! Mais passerelles possibles, en particulier RMI/IIOP

!! Services réduits au minimum

!! Service élémentaire de noms (sans attributs)

!! Pas de services additionnels

"! Duplication d’objets

"! Transactions

Ce qui reste à voir

51

!! Parallélisme sur le serveur

!! Un serveur RMI peut servir plusieurs clients. Dans ce cas, un

thread séparé est créé pour chaque client sur le serveur.

C’est au développeur du programme serveur d’assurer leur

bonne synchronisation (exemple : méthodes synchronized)

pour garantir la cohérence des données

!! Activation automatique de serveurs

!! Un veilleur (demon) spécialisé, rmid, peut assurer le

lancement de plusieurs classes serveur sur un site distant

(cette opération est invisible au client)

!! Téléchargement de code

!! Un chargeur spécial (ClassLoader) peut être développé

pour assurer le téléchargement des classes nécessaires