Verteilte Systeme Verteilte Objektorientierte Systeme I Prof. Dr. Oliver Haase 1 Überblick Verteilte Objektorientierte Systeme 1 ‣ RPC ‣ verteilte objektorientierte Architekturen ‣ Java RMI Verteilte Objektorientierte Systeme 1I ‣ CORBA 2 Remote Procedure Call (RPC) ‣ definiert und entwickelt in den 1980er Jahren ‣ standardisiert von der IETF (Internet Engineering Task Force) ‣ bekannteste Implementierung von Sun Microsystems für Unix ‣ Grundlage verteilter OO-Architekuren: Java RMI, CORBA, DCOM, .Net–Remoting ‣ Wesentliche Idee: Verwende für Kommunikation zwischen Prozessen dasselbe Prinzip wie für lokalen Prozeduraufruf → Ortstransparenz für Entwickler. 3 Remote Procedure Call (RPC) ‣ Grundsätzlicher Ablauf eines Prozedurfernaufrufs: 1. Aufrufender Prozess A schickt entfernter Prozedur B die Eingabeparameter. 2. B führt die entsprechende Funktionalität aus, während A wartet. 3. B schickt die Rückgabeparameter und das Funktionsergebnis zurück zu A. ‣ Synchrone Kommunikation → Sender schickt Anfrage (Prozeduraufruf) zum Empfänger, wartet auf Ergebnis und setzt erst dann seinen Programmablauf fort. 4 RPC-Feinablauf I ‣ Spezifikation der entfernten Prozedur in einem C-Headerähnlichen Format. ‣ Implementierung der Prozedur in C. ‣ RPC-Generator rpcgen generiert aus Spezifikation zwei Stubs: 1) Klienten-Stub: hat Namen der RPC-Prozedur, muss auf Klientenrechner laufen. 2) Server-Stub: läuft auf Servermaschine. ‣ Klient ruft gewünschte RPC-Prozedur auf. 5 RPC-Feinablauf II ‣ Aufruf wendet sich an den (gleichnamigen) Klienten-Stub, der lokal auf derselben Maschine läuft. ‣ Stub konvertiert Eingabeparameter in plattformunabhängiges Datenformat XDR (External Data Representation) → Parameter-Marshalling. ‣ Klienten-Stub verschickt Parameter über das Netz zum Server-Stub. ‣ Server-Stub konvertiert die Parameter zurück in das Format seiner Host-Maschine (Demarshalling) und ruft die eigentliche Serverprozedur auf. 6 RPC-Feinablauf III ‣ Nach Beendigung der Serverprozedur schickt Server-Stub Ausgabeparameter und Ergebnis nach demselben Schema zurück zum Klienten-Stub. ‣ Klienten-Stub gibt Ergebnisse nach oben zum Anwendungsprozess, der den Eindruck hat, als habe der Klienten-Stub die Berechnung selbst durchgeführt. 7 RPC - Graphischer Ablauf ProzedurSpezifikation Klient lokaler Aufruf rpcgen Server lokaler Aufruf generiert automatisch Klienten Stub Netzwerk Kommunikation 8 Server Stub Verteilte OO-Architekturen ‣ Grundlage: Methodenfernaufruf, entfernter Methodenaufruf (Remote Method Invocation) → Übertragung des Prinzips des Prozedurfernaufrufs auf OO-Programmierung ‣ Unterschied: nicht einzelne Methoden, sondern entfernte Objekte werden entfernt bereitgestellt ‣ Verwendung entfernter Methode (fast) wie lokaler Methodenaufruf 9 Verteilte OO-Architekturen ‣ Client–Server–Kommunikation als Methodenaufruf und Ergebnisrückgabe // client code result = server.<method>(<params>); 10 Verteilte OO-Architekturen aus: [Tanenbaum, van Steen. Verteilte Systeme: Grundlagen und Paradigmen] 11 Java Remote Method Invocation (Java RMI) 12 Allgemeines ‣ Java RMI ist eine konkrete Instantiierung des allgemeinen Remote-Method-Invocation-Paradigmas ‣ Plattformunabhängig, aber sprachspezifisch 13 Java-RMI-Schichtenmodell ‣ Für Java Version < 5 Client Server Stub Skeleton Remote-Reference-Schicht Remote-Reference-Schicht Transport-Schicht Transport-Schicht Stub wird auch entfernte Objektreferenz (remote object reference) genannt. 14 Java-RMI-Schichtenmodell ‣ Für Java Version ≥ 5 Client Stub Server Remote-Reference-Schicht Remote-Reference-Schicht Transport-Schicht Transport-Schicht Seit Java 5 wird die Funktion der Skeletons vom RMI–Laufzeitsystem mitübernommen. 15 Stubs und Skeletons Java Version < 5 ‣ RMI–Compilers rmic hat aus Schnittstellenspezifikation Stub– und Skeleton–Klassen generiert → analog rpcgen Java Version ≥ 5 ‣ Fü̈r Client-Stubs werden dynamische Proxies der Reflektionsklasse java.lang.reflect.Proxy verwendet ‣ Skeletons sind nicht mehr notwendig ‣ rmic nicht mehr notwendig! 16 Java RMI aus Sicht des Servers (1) Definition einer entfernten Schnittstelle, die alle entfernt zugreifbaren Methoden enthält (2) Kodieren einer Klasse, die diese Schnittstelle implementiert (3) Erzeugen eines Serverobjekts (4) Exportieren des Serverobjekts, d.h. • Erzeugen eines Klientenstubs • Anbinden an Remote–Reference–Schicht (horchen auf einem TCP–Port) (5) Ggf. Anbinden des Serverobjekts an RMI–Registry 17 (1) Entfernte Schnittstelle ‣ Entfernte Schnittstelle muss java.RMI.Remote erweitern → Markiererschnittstelle ohne Methoden ‣ Jede entfernte Methode kann eine RemoteException werfen ‣ Beispiel: import java.rmi.*; public interface IPrinter extends Remote { PrintJob print(File file) throws RemoteException; boolean cancel(PrintJob job) throws RemoteException; } ‣ Beachte: Deklarierter Exception–Typ kann allgemeiner sein als java.rmi.RemoteException 18 (2) Server-Implementierung ‣ Bereitstellen einer Server–Klasse, die die in entfernter Schnittstelle deklarierten Methoden definiert → weitere Methoden möglich, aber nicht entfernt zugreifbar public class ColorPrinter implements IPrinter { private Map<PrintJob, File> jobs; public ColorPrinter () { jobs = new HashMap<PrintJob , File >(); } public PrintJob print(File file) throws RemoteException { PrintJob job = new PrintJob (); jobs.put(job, file); return job ; } public boolean cancel ( PrintJob job ) throws RemoteException { return ( jobs .remove(job) == null ); } } 19 (3) & (4): Serverobjekt Erzeugen und Exportieren Zwei Varianten: a) Server-Klasse erweitert UnicastRemoteObject → neu erzeugtes Objekt wird automatisch exportiert public class ColorPrinter implements IPrinter extends UnicastRemoteObject { ... } .. . IPrinter stub = new ColorPrinter(); 20 (3) & (4): Serverobjekt Erzeugen und Exportieren b) Explizite Verwendung der statischen Methode UnicastRemoteObject.exportObject() public class ColorPrinter implements IPrinter { ... } .. . IPrinter stub = (IPrinter) UnicastRemoteObject.exportObject(new ColorPrinter(), 0); ‣ 1. Param: muss Typ Remote haben ‣ 2. Param: TCP-Port, auf dem Objekt hört (0 → Systemwahl) ‣ Ergebnis: Client-Stub vom Typ Remote 21 Java RMI aus Sicht des Klienten (1) Beschaffen einer entfernten Objektreferenz (eines Stubs) (2) Aufruf entfernter Methoden (inkl. Reagieren auf RemoteException) private void printFile(IPrinter printer) { JFileChooser chooser = new JFileChooser (); int ret = chooser.showOpenDialog(null); if (returnVal == JFileChooser.APPROVEOPTION) { try { printer.print (chooser.getSelectedFile()); } catch (RemoteException e) { JOptionPanel.showMessageDialog(null, ”couldn’t print file”); } } } 22 RMI Registry ‣ Namensdienst zum initialen Beschaffen einer entfernten Referenz ‣ selbst RMI-Serverobjekt ‣ Teil des Java SDK ‣ hält Mappings: Namen → Client-Stub, Namen können frei gewählt werden ‣ Verteilungsmodel: RMI Registry läuft auf selbem Rechner wie registrierte Serverobjekte • Grund: Sicherheitskonzept, da Stubs ohne Authentisierung registriert und überschrieben werden können 23 RMI Registry ‣ Mappings werden nicht persistent gespeichert - Bindings gehen verloren, wenn Registry neu startet → Server sollten sich regelmäßig re-registrieren ✓schützt Registry vor Vermüllung mit Mappings, die schon lange ungültig sind. ‣ Soft State Computing ‣ Namensschema: • hierarchische Namen 24 RMI Registry aus Serversicht ‣ Serverseitige Methoden der Schnittstelle Registry void bind(String name, Remote obj); void rebind(String name, Remote obj); void unbind(String name); ‣ Zwei Varianten zum Starten der RMI Registry: 1) Registry per Kommandozeile starten 2) Registry programmatisch starten 25 RMI Registry aus Serversicht 1) Registry per Kommandozeile starten: $rmiregistry Im Serverprogramm: Registry registry = LocateRegistry.getRegistry(); IPrinter stub = (IPrinter) UnicastRemoteObject.exportObject(new ColorPrinter(), 0); registry.rebind(“g124-color-duplex”, stub); 26 RMI Registry aus Serversicht 2) Registry programmatisch starten: Registry registry = LocateRegistry.createRegistry( Registry.REGISTRY_PORT); IPrinter stub = (IPrinter) UnicastRemoteObject.exportObject(new ColorPrinter(), 0); registry.rebind(“g124-color-duplex”, stub); ‣ Lebensdauer(rmiregistry) = Lebensdauer(aufrufende JVM) 27 RMI Registry aus Klientensicht ‣ Clientseitige Methoden der Schnittstelle Registry Remote lookup(String name); String[] list(); ‣ Beispiel: Registry registry = LocateRegistry.getRegistry( “sunja.htwg-konstanz.de”); IPrinter printer = (IPrinter) registry.lookup(“g124-color-duplex”); 28 Parameterübergabemechanismen ‣ Frage: Passt der Java-Parameterübergabemechanismus auch auf entfernte Methodenaufrufe? ‣ Wiederholung: lokale Methodenaufrufe: • primitive Werte - Call by Value • Referenzen - Call by Value, d.h. Referenz auf Objekt bzw. Array wird in aufgerufene Methode kopiert • Ergebnisrückgabe - analog 29 Parameterübergabemechanismen ‣ Entfernte Methodenaufrufe: • primitive Werte - kein Problem, zum entfernten Objekt schicken • Referenzen - sind im entfernten Prozess ungültig, was tun? - Referenz auf RMI-Serverobjekt • Stub (entfernte Referenz) übertragen, entspricht lokalem Fall • gilt nur für exportierte Serverobjekte - Referenz auf sonstiges Objekt (oder auf Array) • • • • komplettes Objekt wird serialisiert und übertragen entspricht nicht lokalem Methodenaufruf gilt auch für nichtexportiertes RMI-Serverobjekt Objekt muss serialierbar sein 30 Parameterübergabemechanismen o2.f(o3) o4 o1 o2 o4 o3 31 Dynamisches Klassennachladen ‣ Szenario: Bei entferntem Methodenaufruf wird Objekt verschifft (als Parameter oder als Ergebnis), für das auf der empfangenden Seite keine Klassendefinition vorliegt. ‣ Wie kann das passieren? – Server und Klient müssen doch die Methodensignatur und alle darin verwendeten Typen kennen, um überhaupt compilierbar zu sein? . . . ‣ Antwort: Substitutionsprinzip - Sender hat spezielleres Objekt für allgemeineren Typ eingesetzt (Subklasse statt angegebene Klasse, Implementierung statt angegebener Schnittstelle). 32 Dynamisches Klassennachladen ‣ Fehlende Klassen können vom Objektempfänger dynamisch nachgeladen werden, falls diese auf HTTP-Server liegen und Client-Stub diese Lokation als codebase mit sich führt. ‣ Vor Stub-Generierung (Objektexport) muss codebaseProperty der JVM passend gesetzt werden • als Kommandozeilenparameter beim JVM-Start • programmatisch über System.setProperty() ‣ Dyn. Klassennachladen erfordert, das Client unter Kontrolle eines Sicherheitsmanagers läuft. 33