Cours JAVA RMI [PDF]

  • 0 0 0
  • Gefällt Ihnen dieses papier und der download? Sie können Ihre eigene PDF-Datei in wenigen Minuten kostenlos online veröffentlichen! Anmelden
Datei wird geladen, bitte warten...
Zitiervorschau

Applications Réparties Java Remote Method Invocation

Atef Ben Ismail

INSAT 2009-2010

Intérêt des objets pour la construction d’applications réparties  Encapsulation • L’interface (méthodes + attributs) 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 récupération et réutilisation de l’existant

 Polymorphisme • Mises en œuvre diverses des fonctions d’une interface • Remplacement d’un objet par un autre si interfaces • Facilite l’évolution et l’adaptation des applications

2 Application Réparties

INSAT 2010

Java RMI  Motivation : construction d’applications réparties avec Java • Appel de méthode au lieu d’appel de procédure • Invocation des méthodes sur des objets s’exécutant sur une autre JVM (même ordinateur ou sur un autre ordinateur du réseau)

 Principe : même schéma que RPC • Le programmeur fournit  Une (ou plusieurs) description(s) d’interface – Ici pas d’IDL séparé : Java sert d’IDL  Le programme du serveur – Objets réalisant les interfaces – Serveur  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/ 3 Application Réparties

INSAT 2010

RMI est pur Java  Avec RMI, le serveur et le client doivent être écrit en java  Le ramasse miettes est distribué sur le réseau Un objet est détruit du serveur s’il n’est plus référencé

 RMI est une interface de programmation indépendante du protocole Par défaut RMI utilise le protocole JRMP (protocole propriétaire SUN) RMI fonctionne aussi avec le protocole CORBA: IIOP

4 Application Réparties

INSAT 2010

Fonctionnement de RMI: Serveur  Fonctionnement côté serveur : 1) L'objet serveur s'enregistre auprès du service de noms RMI via la classe Naming de sa JVM (méthode bind ou rebind) 2) L'objet squelette (skeleton) est créé, celui-ci crée le port de communication et maintient une référence vers l'objet serveur 3) Le Naming enregistre l'objet serveur, et le port de communication utilisé auprès du serveur de noms.

 Skeleton • Invoque des méthodes sur l'objet local référencé pour le compte d'une souche • Convertit les valeurs de retour en un format transmissible via le réseau (marshalling) • Reconstruit les arguments à partir de données reçues par le réseau (unmarshalling) • Il n‘est plus indispensable depuis le JDK 1.2 Invocation méthode

Stub

Skeleton

5 | A look Forward | January 2010

réponse

Implémentation

Fonctionnement de RMI: Client  Fonctionnement côté client : 1) L'objet client fait appel au Naming de sa JVM pour localiser l'objet serveur (méthode lookup) 2) Le Naming récupère une "référence" vers l'objet serveur, … 3) Crée l'objet souche et … 4) Renvoie la référence de la souche au client 5) Le client appelle des méthodes de l'objet serveur au travers de la souche (Stub) et du squelette (skeleton).

 Stub • Représente un objet distant • Convertit les arguments en un format transmissible via le réseau (marshalling) • Reconstruit les valeurs de retour à partir de données reçues par le réseau (unmarshalling) Invocation méthode

Objet Client

réponse

6 | A look Forward | January 2010

Stub

Skeleton

Fonctionnement de RMI  Lorsqu'un objet instancié sur une machine cliente désire accèder à des méthodes d'un objet distant, il effectue les opérations suivantes : • il localise l'objet distant grâce à un service de nommage: le registre RMI • il obtient dynamiquement une image virtuelle de l'objet distant (appelée stub ou souche en français). Le stub possède exactement la même interface que l'objet distant. • Le stub transforme l'appel de la méthode distante en une suite d'octets, c'est ce que l'on appelle la sérialisation, puis les transmet au serveur instanciant l'objet sous forme de flot de données. On dit que le stub "marshalise" les arguments de la méthode distante. • Le squelette instancié sur le serveur "désérialise" les données envoyées par le stub (on dit qu'il les "démarshalise"), puis appelle la méthode en local • Le squelette récupère les données renvoyées par la méthode (type de base, objet ou exception) puis les marshalise • le stub démarshalise les données provenant du squelette et les transmet à l'objet faisant l'appel de méthode à distance

7 | A look Forward | January 2010

Enregistrement d'un service

8 | A look Forward | January 2010

Accès à une référence distante

9 | A look Forward | January 2010

Invocation d'une méthode

10 | A look Forward | January 2010

Architecture générale de RMI

11 | A look Forward | January 2010

Qu’est ce qu’un Proxy?  Un objet distribué est accédé via un Proxy Le Proxy est l’objet distribué implémentant la même interface Le Proxy transmet les invocations de méthodes sur le réseau, vers l’objet distribué L’objet distribué contient le code à exécuter

 Le Stub est la classe d’un Proxy

12 Application Réparties

INSAT 2010

Annuaire ou Service de nommage  Obtention d'une première référence sur un objet distant : « bootstrap » à l’aide d’un Service de Nommage ou Annuaire  Enregistrement des références d'objets dans l'annuaire afin que des programmes distants puissent les récupérer

13 | A look Forward | January 2010

Exemple: Le RMIRegistry (1/2)  Implémentation d'un service de nommage  Fourni en standard avec RMI  Permet d'enregistrer des références sur des objets de serveur afin que des clients les récupèrent  On associe la référence de l'objet à une clé unique (chaîne de caractères)  Le client effectue une recherche par la clé, et le service de nommage lui renvoie la référence distante (le stub) de l'objet enregistré pour cette clé

14 | A look Forward | January 2010

Le RMIRegistry (2/2)  Programme exécutable fourni pour toutes les plates formes  S'exécute sur un port (1099 par défaut) sur la machine serveur  Pour des raisons de sécurité, seuls les objets résidant sur la même machine sont autorisés à lier/délier des références  Un service de nommage est lui-même localisé à l'aide d'une URL

15 | A look Forward | January 2010

La classe java.rmi.Naming  permet de manipuler le RMIRegistry  supporte des méthodes statiques permettant de • Lier des références d'objets serveur – Naming.bind(...) et Naming.rebind(...)

• Délier des références d'objets serveur – Naming.unbind(...)

• Lister le contenu du Naming – Naming.list(...)

• Obtenir une référence vers un objet distant – Naming.lookup(...)

16 | A look Forward | January 2010

Java RMI : règles d’usage (1/2)  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

17 Application Réparties

INSAT 2010

Java RMI : règles d’usage (2/2)  Réalisation 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 • Une classe distante peut aussi avoir des méthodes appelables seulement localement (ne font pas partie de son interface Remote)

18 Application Réparties

INSAT 2010

Passage de paramètres/données  Lors d'appel de méthodes distantes : 4 cas pour gérer les paramètres ou la valeur retournée selon la classe du paramètre • Si classe implémente Remote : passage par adresse  On passe ou récupère la référence sur un objet distant

• Si classe n'implémente pas Remote : passage par valeur  L'objet est cloné, on passe ou récupère une copie de l'objet

• Pour types primitifs : passage par valeur également • Si classe n'implémente pas Serializable : objet ne peut pas être paramètre ou la classe ne peut pas être un type de retour  Les paramètres ou valeurs de retour sont forcément sérialisés pour être transmis via le réseau

19 | A look Forward | January 2010

Java RMI : règles d’écriture du serveur  Un serveur est une classe qui implémente l’interface de l’objet distant • Spécifier les références distantes qui doivent être implémentées (objets passés en paramètres) • Définir le constructeur de l’objet distant • Fournir la réalisation 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

20 | A look Forward | January 2010

RMI: Cycle de Développement (1/2)  Définition de l'interface de l'objet distant : • interface héritant de java.rmi.Remote • méthodes : "throws java.rmi.RemoteException"

 Ecrire une implémentation : • classe héritant de java.rmi.server.UnicastRemoteObject et implémentant l'interface précédente. • paramètres de type simple, objets sérialisables : "implements Serializable" ou souches • écrire un main permettant l'enregistrement auprès du Naming

 Ecriture d'un client • utilisation du Naming pour trouver l'objet distant • appel(s) de méthodes

21 | A look Forward | January 2010

RMI: Cycle de Développement

22 Application Réparties

INSAT 2010

Java RMI : Étapes de la mise en œuvre (1/2)  Compilation • Sur la machine serveur : compiler les interfaces et les programmes du serveur javac .java .java .java

• Sur la machine serveur : créer les talons client et serveur pour les objets appelés à distance (à partir de leurs interfaces) - ici une seule classe, Hello rmic –keep

N.B. cette commande construit et compile les talons client _Stub.java et serveur _Skel.java. L’option -keep permet de garder les sources de ces talons • Sur la machine client : compiler les interfaces et le programme client javac .java .java

N.B. il est préférable de regrouper dans un fichier .jar les interfaces des objets appelés à distance, ce qui permet de les réutiliser pour le serveur et le client -

23 Application Réparties

INSAT 2010

Java RMI : Étapes de la mise en œuvre (2/2)  Exécution • Lancer le serveur de noms (sur la machine serveur) rmiregistry &

N.B. Par défaut, le registry écoute sur le port 1099. Si on veut le placer sur un autre port, il suffit de l’indiquer, mais il faut aussi modifier les URL en conséquence : rmi://:/

• Lancer le serveur java -Djava.rmi.server.codebase=http:/// -D java.security.policy=java.policy & N.B. Signification des propriétés (option -D) : – Le contenu du fichier java.policy spécifie la politique de sécurité. – L’URL donnée par codebase sert au chargement de classes par le client

• Lancer le client java -Djava.security.policy=java.policy N.B. Le talon client sera chargé par le client depuis le site du serveur, spécifié dans l’option codebase lors du lancement du serveur

24 Application Réparties

INSAT 2010

Exemple HelloWorld Pas à Pas

Exemple: Hello World

26 Application Réparties

INSAT 2010

Les Etapes 1- Définir les packages 2- Créer les interfaces 3- Coder les objets passés par valeur 4- Coder les objets sur le serveur 5- Ecrire le main() sur le serveur 6- Lancer rmiregistry et le serveur 7- Coder et lancer le client

27 | A look Forward | January 2010

Définir les packages  Il est préférable mais pas obligatoire de : Placer le code du client et du serveur dans des packages différents Placer les interfaces distribuées dans un troisième package

helloworld

helloworld.client

import

Helloworld.intfc

28 | A look Forward | January 2010

import

helloworld.server

Interfaces et classes prédéfinies

29 Application Réparties

INSAT 2010

Interface = protocole d ’application  L ’interface HelloWorld

import java.rmi.*; interface HelloWorld extends Remote { public String sayHello() throws RemoteException; }

30 Application Réparties

INSAT 2010

Rôle de l’interface HelloWorld

31 | A look Forward | January 2010

Exception  L ’exception RemoteException doit être déclarée par toutes les méthodes distantes • Appels de méthodes distants moins fiables que les appels locaux – Serveur ou connexion peut être indisponible – Panne de réseau – ...

32 | A look Forward | January 2010

Du côté client HelloWorld hello = ...; // Nous verrons par la suite comment obtenir // une première référence sur un stub String result = hello.sayHello(); System.out.println(result);

33 Application Réparties

INSAT 2010

Du côté Serveur  Implémentation de la classe qui gère les méthodes de l ’interface HelloWorld // Classe d'implémentation du Serveur public class HelloWorldImpl extends UnicastRemoteObject implements HelloWorld { public String sayHello() throws RemoteException { String result = « hello world !!! »; System.out.println(« Méthode sayHello invoquée... » + result); return result; } }

34 Application Réparties

INSAT 2010

Classe d’implémentation  Doit implémenter l’interface HelloWorld  Doit étendre la classe RemoteServer du paquetage java.rmi  RemoteServer est une classe abstraite  UnicastRemoteObject est une classe concrète qui gére la communication et les stubs

35 Application Réparties

INSAT 2010

Classe d’implémentation HelloWorld

HelloWorldImpl

36 Application Réparties

INSAT 2010

L’outil RMIC  Outil livré avec le JDK permet de générer les stubs > rmic HelloWorldImpl génère un fichier HelloWorldImpl_stub.class

rmic doit être passé pour toutes les classes d'implémentation des Object Distribués afin d'en générer les stubs

37 Application Réparties

INSAT 2010

Enregistrement d ’une référence L ’objet serveur HelloWorld (coté serveur bien entendu…)  On a créé l'objet serveur et on a une variable qui le référence HelloWorld hello = new HelloWorldImpl();  On va enregistrer l'objet dans le RMIRegistry Naming.rebind("HelloWorld",hello);  L'objet est désormais accessible par les clients

38 Application Réparties

INSAT 2010

Obtention d'une référence coté client sur l'objet serveur HelloWorld  On déclare une variable de type HelloWorld et on effectue une recherche dans l'annuaire HelloWorld hello = (HelloWorld)Naming.lookup("rmi://www.helloworldserver.com/HelloWorld");

 On indique quelle est l'adresse de la machine sur laquelle s'exécute le RMIRegistry ainsi que la clé  La valeur retournée doit être transtypée (castée) vers son type réel

39 Application Réparties

INSAT 2010

Remarque  Le Service de Nommage n'a pas pour fonction le référencement de tous les objets de serveur • Il devient vite complexe de gérer l'unicité des clés

 La règle de bonne utilisation du Naming est de lier des objets qui font office de point d'entrée, et qui permettent de manipuler les autres objets serveurs

40 Application Réparties

INSAT 2010

Conception, implémentation et exécution de l'exemple  Rappel • On veut invoquer la méthode sayHello() d'un objet de serveur distant de type HelloWorld depuis un programme Java client

 Nous allons devoir coder • L'objet distant • Le serveur • Le client • « Et définir les permissions de sécurité et autres emplacements de classes... »

41 Application Réparties

INSAT 2010

Hello World : L'objet distant  Une interface et une classe d'implémentation  stubs générés automatiquement par rmic  toutes les classes nécessaires à l’objet de client doivent être déployées sur la machine cliente et accessibles au chargeur de classes (dans le CLASSPATH) • L'interface HelloWorld (HelloWorld.class) • Le stub HelloWorldImpl_stub généré par rmic pour cet objet

42 Application Réparties

INSAT 2010

Hello World : Le serveur  instancie un objet de type HelloWorld et attache au service de nommage  puis objet mis en attente des invocations jusqu'à ce que le serveur soit arrêté

43 Application Réparties

INSAT 2010

Hello World : Le serveur import java.rmi.*; import java.rmi.server.*; public class HelloWorldServer { public static void main(String[] args) { try { System.out.println("Création de l'objet serveur..."); HelloWorld hello = new HelloWorldImpl(); System.out.println("Référencement dans le RMIRegistry..."); Naming.rebind("HelloWorld",hello); System.out.println("Attente d'invocations - CTRL-C pour stopper"); } catch(Exception e) { e.printStackTrace(); } } } 44 Application Réparties

INSAT 2010

Serveur suite  Apres avoir compilé le tout...  Pour démarrer le serveur, il faut tout d'abord lancer le RMIRegistry Attention : La base de registres RMI doit connaître les interfaces et les stubs des objets qu'elle enregistre (CLASSPATH) !!!

> rmiregistry &  et ensuite on lance le serveur > java HelloWorldServer  création de l'objet serveur...  Référencement dans le RMIRegistry...  Attente d'invocations - CTRL-C pour stopper

45 Application Réparties

INSAT 2010

Hello World : client  Obtenir une référence sur l'objet de serveur HelloWorld, invoquer la méthode sayHello(), puis afficher le résultat de l'invocation sur la sortie standard

46 | A look Forward | January 2010

Hello World : client import java.rmi.*; public class HelloWorldClient { public static void main(String[] args) { try { System.out.println("Recherche de l'objet serveur...");

HelloWorld hello = (HelloWorld)Naming.lookup("rmi://server/HelloWorld"); System.out.println("Invocation de la méthode sayHello...");

String result = hello.sayHello(); System.out.println("Affichage du résultat :"); System.out.println(result); System.exit(0); } catch(Exception e) { e.printStackTrace(); } } }

47 Application Réparties

INSAT 2010

Client suite  Il suffit ensuite de lancer le programme > java HelloWorldClient  Recherche de l'objet serveur...  Invocation de la méthode sayHello...  Affichage du résultat :  hello world !!!

 Au niveau du serveur, le message... Méthode sayHello invoquée... hello world !!!  ...s'affichera dans la console

48 Application Réparties

INSAT 2010

Que doit connaître le client ?  Lorsqu’un objet serveur est passé à un programme, soit comme paramètre soit comme valeur de retour, ce programme doit être capable de travailler avec le stub associé  Le programme client doit connaître la classe du stub  les classes des paramètres, des valeurs de retour et des exceptions doivent aussi être connues... • Une méthode distante est déclarée avec un type de valeur de retour... • ...mais il se peut que l’objet réellement renvoyé soit une sous-classe du type déclaré

49 Application Réparties

INSAT 2010

Que doit connaître le client ?  Le client doit disposer des classes de stub, classes des objets retournés… • Copier les classes sur le système de fichiers local du client (CLASSPATH)... • ...cependant, si le serveur est mis à jour et que de nouvelles classes apparaissent, il devient vite pénible de mettre à jour le client • C’est pourquoi les clients RMI peuvent charger automatiquement des classes de stub depuis un autre emplacement – Il s ’agit du même type de mécanisme pour les applets qui fonctionnent dans un navigateur

50 Application Réparties

INSAT 2010

Chargement dynamique des classes  Problème de sécurité • Le programme client télécharge du code sur le réseau • Ce code pourrait contenir des virus ou effectuer des opérations non attendues !!! • Utilisation d ’un gestionnaire de sécurité pour les applications de clients RMI • Possibilité de créer des gestionnaires de sécurité personnalisés pour des applications spécifiques • RMI fournit des gestionnaires de sécurité suffisants pour un usage classique

51 Application Réparties

INSAT 2010

Chargement dynamique  Pour ne plus déployer les classes du serveur chez le client • Utilisation des chargeurs de classes qui téléchargent des classes depuis une URL • Utilisation d’un serveur Web qui fournit les classes

 Ce que ça change • Bien entendu, les classes et interfaces de l’objet distant ne changent pas • Le code du serveur ne change pas

le client et la façon de le démarrer sont modifiés Et lancer un serveur Web pour nos classes

52 Application Réparties

INSAT 2010

Hello World : chargement dynamique Séparation des classes  Serveur (fichiers nécessaires a l'exécution du serveur) HelloWorldServer.class HelloWorldImpl.class HelloWorld.class HelloWorldImpl_Stub.class

 Download (fichiers de classes à charger dans le programme client) HelloWorldImpl_Stub.class

 Client (fichiers nécessaires au démarrage du client) HelloWorld.class HelloWorldClient.class

53 Application Réparties

INSAT 2010

Hello World : Démarrage du serveur Web Mettre les classes Download dans le répertoire des documents Web du serveur Web, accessibles via une URL  le chargeur de classes ira chercher les classes à un emplacement de type http://www.class-server.com/classes/HelloWorldImpl_Stub.class

54 Application Réparties

INSAT 2010

Hello World : Politiques de sécurité  Le programme Java client doit pouvoir se connecter aux ports de la base de registres RMI et des implémentations des objets de serveur, ainsi qu'au port du serveur Web  Fichier client.policy grant { permission java.net.SocketPermission "*:1024-65535", "connect,resolve"; permission java.net.SocketPermission "*:80", "connect"; };

55 Application Réparties

INSAT 2010

Hello World : gestionnaire de sécurité RMI  Le client intègre un gestionnaire de sécurité RMI pour les stubs téléchargés dynamiquement import java.rmi.*; import java.rmi.server.*; public class HelloWorldClient { public static void main(String[] args) { try { // Installe un gestionnaire de sécurité RMI System.setSecurityManager(new RMISecurityManager()); System.out.println("Recherche de l'objet serveur..."); HelloWorld hello = (HelloWorld)Naming.lookup("rmi://server/HelloWorld"); System.out.println("Invocation de la méthode sayHello..."); String result = hello.sayHello(); System.out.println("Affichage du résultat :"); System.out.println(result); } catch(Exception e) { e.printStackTrace(); } } } 56 Application Réparties

INSAT 2010

Hello World : Démarrage coté serveur 1. Lancer la base de registres RMI (elle doit pouvoir accéder aux classes Download - CLASSPATH) > rmiregistry 2. Lancer le serveur Web servant les fichiers de classes Download 3. Lancer le serveur (les classes Server doivent être accessibles) > java HelloWorldServer Création de l'objet serveur... Référencement dans le RMIRegistry... Attente d'invocations - CTRL-C pour stopper

57 Application Réparties

INSAT 2010

Hello World : Démarrage coté client  Le client doit pouvoir se connecter à des machines distantes pour la base de registres RMI, les objets de serveur ainsi que le serveur Web On doit lui fournir un fichier client.policy

 Le client doit bien connaître l'emplacement des classes afin de pouvoir les télécharger On va le lui préciser lors du lancement java -Djava.security.policy=client.policy -D java.rmi.server.codebase=http://www.class-server.com:80/ HelloWorldClient

58 Application Réparties

INSAT 2010

Erreurs classiques (1/2)  Stub inaccessible au rmiregistry java.rmi.ServerException: RemoteException occurred in server ... java.rmi.UnmarshalException: error unmarshalling ... java.lang.ClassNotFoundException:

Le stub est accessible au serveur MAIS PAS AU rmiregistry Attention à l’ordre d’appel : génération des stubs et appel du rmiregistry

 rmiregistry pas lancé java.net.ConnectException

 Oubli du constructeur pour le RemoteObject unreported exception java.rmi.RemoteException in default constructorpublic class HelloImpl extends UnicastRemoteObject implements Hello { ^

 rmiregistry déjà lancé java.rmi.server.ExportException: Port already in use: 1099

On peut lancer un autre registry mais sur un autre port. 59 Application Réparties

INSAT 2010

Erreurs classiques (2/2)  La classe d’implémentation n'hérite pas de UnicastRemoteObject S'il n'hérite pas de UnicastRemoteObject, il n'est pas Remote donc on lui demande d'être Serializable ... Trouble: java.rmi.MarshalException: error marshalling arguments; nested exception Is: java.io.NotSerializableException: CalculatorImpl

60 Application Réparties

INSAT 2010

Une autre utilisation du rmiRegistry import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry;

Client Registry registry; registry = LocateRegistry.getRegistry(); Hello hello = (Hello) registry.lookup("coucou");

Serveur LocateRegistry.createRegistry(port);

//

port=1099

Hello stub = (Hello) UnicastRemoteObject.exportObject(unHello, 0); Naming.rebind("rmi://"+"localhost"+":"+ port +"/coucou", stub);

61 Application Réparties

INSAT 2010

www.alcatel-lucent.com INSAT 2009-2010

62 | A look Forward | January 2010