Verteilte Systeme Verteilte Objektorientierte Systeme II Prof. Dr. Oliver Haase 1 Überblick Verteilte Objektorientierte Systeme 1 ‣ RPC ‣ verteilte objektorientierte Architekturen ‣ Java RMI Verteilte Objektorientierte Systeme 1I ‣ CORBA 2 Einführung ‣ Common Object Request Broker Architecture ‣ standardisiert von der Object Management Group (OMG) • Konsortium zahlreicher Firmen und Organisationen • weiterer wichtiger Standard: UML ‣ sprachunabhängig, d.h. Server und Klienten können in unterschiedlichen Sprachen geschrieben sein. ‣ (De–)Marshalling erlaubt verschiedene Sprachen bei Sender und Empfänger ‣ außerdem betriebssystemunabhängig CORBA ermöglicht das Entwickeln heterogener verteilter OO-Systeme 3 Object Management Architecture ‣ CORBA-Architektur: Object Management Architecture (OMA) Application Objects Domain Objects Object Request Broker Common Object Services Common Facilities 4 Object Request Broker (ORB) ‣ Herzstück der OMA ‣ vermittelt (engl: to broker) Anfragen vom Klienten zum entfernten Serverobjekt. ‣ führt Marshalling und Demarshalling durch ‣ vergleichbar mit Remote-Reference–Schicht in Java RMI ‣ jeder Prozess mit CORBA-Objekten Application muss einen ORB besitzen Domain Objects Objects ‣ ORBs kommunizieren über standardisierte Protokolle 1 Object Request Broker miteinander Common Object Services 5 Common Facilities Common Object Services (COS) ‣ Basisdienste, die • über den Methoden–Transport hinausgehen • für sehr viele Anwendungen interessant sind ‣ Beispiele: • Naming Service • Trading Service → attributbasierter Namensdienst • Event Service → asynchrone Kommunikation Application Objects Domain Objects Object Request Broker 2 Common Object Services 6 Common Facilities Common Facilities ‣ Dienste, die über die COS hinausgehen ‣ komplexer, spezieller, seltener genutzt ‣ untergliedert in die Bereiche • • • • Informationsmangement Benutzerschnittstellen Systemmanagement Application Objects Taskmanagement Domain Objects Object Request Broker Common Object Services 7 Common Facilities 3 Domain Objects ‣ noch spezieller auf Anwendungsbereich zugeschnitten, z.B. Telekommunikation, Bankwesen, Medizin ‣ vertikale Segmentierung Application Objects Domain Objects 4 Object Request Broker Common Object Services 8 Common Facilities Application Objects ‣ eigentliche Anwendung, verteilt auf Server– und Klientobjekte ‣ kommunizieren über ORB miteinander ‣ können COS, Common Facilities und Domain Objects verwenden ‣ nicht Teil des CORBA–Standards Application Objects Domain Objects 5 Object Request Broker Common Object Services 9 Common Facilities ORB: Methodenfernaufruf Stub Klient Server DII DSI Skeleton Objektadapter GIOP ORB ORB ‣ Klient ruft entfernte Methode am lokalen Stub auf (wird vom IDL–Compiler aus Schnittstellen–Spezifikation erzeugt) ‣ Stub verpackt die Parameter (Marshalling) ‣ ORB ist zuständig für Lokalisieren des Serverobjekts (→ hosting ORB ist in Objektreferenz kodiert) 10 ORB: Methodenfernaufruf Stub Klient Server DII DSI Skeleton Objektadapter GIOP ORB ORB ‣ Server auf entferntem Rechner → ORB kommuniziert mit entferntem ORB über General Inter-ORB Protocol (GIOP) ‣ GIOP bezeichnet Familie von Protokollen, konkrete Instantiierung hängt von verwendetem Transportprotokoll ab ‣ Am häufigsten: Internet Inter-ORB Protocol (IIOP), oberhalb von TCP 11 ORB: Methodenfernaufruf Stub Klient Server DII DSI Skeleton Objektadapter GIOP ORB ORB ‣ ORB auf Serverrechner übergibt Anfrage an Objektadapter ‣ Objektadapter startet ggf. Server ‣ Objektadapter übergibt Anfrage an Skeleton (generiert von IDL–Compiler) ‣ Skeleton entpackt Parameter (Demarshalling) → Server 12 Dynamische Methodenaufrufe ‣ dynamischer Methodenaufruf wird erst zur Laufzeit zusammengesetzt: // vereinfachter Pseudocode invoke(object, method, in_params, out_params); ‣ Vorteil: Erlaubt Methodenaufrufe, die zur Compilierzeit nicht nicht bekannt sind. 13 Dynamische Methodenaufrufe Stub Klient Server DII DSI Skeleton Objektadapter GIOP ORB ORB ‣ Dynamic Invocation Interface (DII) erlaubt Klienten, Server– Schnittstelle dynamisch zu erfragen und entsprechende Methodenaufrufe zu konstruieren (vgl. Java–Introspektion) ‣ Dynamic Skeleton Interface (DSI) nimmt solche Aufrufe serverseitig entgegen 14 Interface Definition Language ‣ Die Implementierung von Applikationsobjekten kann in verschiedenen Sprachen erfolgen ‣ Die Schnittstellenbeschreibung muss jedoch einheitlich erfolgen, damit • jeder Nutzer weiß, wie er ein Objekt ansprechen kann; • Client-Stubs und Server-Skeleton daraus erzeugt werden können. CORBA IDL (Interface Definition Language) ist eine programmiersprachenunabhängige Spezifikationssprache zu diesem Zweck. 15 Interface Definition Language ‣ IDL beschreibt Signaturen (Prototypen) und benötigte Datentypen, keine Implementierung! ‣ Syntax orientiert sich an C++ Methodenspezifikation in IDL C-Klient Java-Klient IDL Compiler C++-Klient C Klienten Stub Java Klienten Stub C++-Server generiert automatisch C++ Klienten Stub Netzwerk Kommunikation 16 C++-Server Stub IDL-Sprach-Mappings ‣ für jede unterstützte Sprache gibt es ein Mapping, derzeit: ADA, C, C++, COBOL, Java, Lisp, PL/I, Python, Smalltalk und XML. ‣ Abbildung von IDL auf Java nicht trivial, da IDL mächtiger als Java: • mehr Typkonstruktoren (Strukturen, Unions, …) • IDL erlaubt, den Parameter–Übergabemechanismus zu spezifizieren 17 IDL-Syntax ‣ Modul: zusammengehörende Definitionen einer Anwendung, enthält: • Datentypen (ähnlich wie in C++, d.h. Klassen, Strukturen, Enums, Unions, …) → werden auf (spezielle) Java-Klassen abgebildet • Schnittstellen, bestehend aus - Methoden - öffentlichen Instanzvariablen → werden auf Getters/Setters abgebildet • Ausnahmen 18 IDL-Syntax ‣ Methoden: Pro Parameter wird Übergabemechanismus spezifiziert: in, out oder inout. ‣ Problem: Java kennt nur Call-by-Value, d.h. in. ‣ Lösung: Abbildung von out- und inout-Params auf Behälterklassen. 19 IDL-Syntax ‣ Beispiel: module QueueApp { struct Person { string firstname; string lastname; unsigned short age; }; exception EmptyQueueException { string message; }; interface Queue { boolean enqueue(in Person person); Person dequeue() raises (EmptyQueueException); boolean isEmpty(); }; }; 20 CORBA Naming Service ‣ Common Object Service zum Beziehen entfernter Objekt- referenzen ‣ Naming Service ist selbst ein CORBA–Objekt ‣ Für Bootstrapping gibt es 2 ORB-Operationen, die COSDienste liefern • list_initial_references: liefert alle am lokalen ORB verfügbaren COS–Dienste, u.a. Naming Service • resolve_initial_references: liefert Referenz auf Dienst mit gegebenem Namen ‣ liefert Referenz auf einen Naming Context 21 CORBA Naming Service ‣ Naming Context kann enthalten: • weitere Naming Contexts, und • Name Bindings: Name → Objektreferenz ‣ erlaubt Aufbau hierarchischer Namensräume pro ORB- eigenem Naming Service ‣ Interoperable Naming Service (INS) erlaubt die Nutzung eines Naming Services von einem entfernten ORB aus • entfernter Naming Service muss beim Start des eigenen ORBs in URL-ähnlicher Form konfiguriert werden. 22 CORBA aus Server-Sicht ‣ Erstellen und Starten eines CORBA–Serverobjekts besteht aus folgenden Schritten: 1) Erstellen einer IDL–Spezifikation 2) Implementieren des Serverobjekts 3) Erzeugen einer CORBA–Referenz 4) Starten des Serverobjekts 23 1) Erstellen einer IDL-Spezifikation ‣ Zum Beispiel in einer Datei hello.idl wie folgt: module HelloApp { interface Hello { string sayHello(in string name); }; }; ‣ Durch Aufruf von $idlj -fserver hello.idl erzeugt der Java-SDK-eigene IDL-Java-Compiler die serverseitigen Generate (z.B. Server-Skeleton) 24 2) Implementieren des Server-Objekts ‣ Implementierung HelloImpl muss den generierten portablen Objektadapter HelloPOA erweitern: class HelloImpl extends HelloPOA { public String sayHello(String name) { return (name.equals(“”)) ? “Hello!” : “Hello, “ + name + “!”; } } ‣ Beachte: Strings sind Basistyp in IDL → kein null–Werte möglich! 25 3) Erzeugen einer CORBA-Referenz ‣ ORB initialisieren • dabei zu verwendende ORB-Implementierung angeben ‣ Referenz auf Root POA besorgen ‣ Root POA aktivieren ‣ Referenz auf Naming Service (Naming Context) besorgen ‣ Serverobjekt instantiieren, CORBA-Referenz erzeugen ‣ CORBA-Referenz an Naming Service binden ‣ ORB starten • hält den Server-Prozess am Leben 26 3) Erzeugen einer CORBA-Referenz class HelloServer { public static void main(String args []) throws Exception { ORB orb = ORB.init(args, null); POA rootpoa = POAHelper.narrow( orb.resolve_initial_references(”RootPOA”)); rootpoa.thePOAManager().activate(); NamingContextExt nameService = NamingContextExtHelper.narrow( orb.resolve_initial_references(”NameService”)); org.omg.CORBA.Object ref = rootpoa.servant_to_reference( new HelloImpl()); Hello server = HelloHelper.narrow(ref); nameService.rebind(nameService.to_name(”HelloServer”), server); orb.run(); } } 27 4) Starten des Serverobjekts ‣ Starten des Naming Service $tnameserv -ORBInitialPort 1050 • horcht defaultmäßig auf Port 900 → darf auf Unix-System nur von Systemapplikation verwendet werden ‣ Starten des Serverapplikationsobjekts $java HelloServer -ORBInitialPort 1050 28 CORBA aus Client-Sicht ‣ Durch Aufruf von $idlj -fclient hello.idl erzeugt der Java-SDK-eigene IDL-Java-Compiler die clientseitigen Generate (z.B. Client-Stub) ‣ Umgang mit CORBA besteht auf Client-Seite aus drei Schritten: 1) Beschaffen einer entfernten Referenz 2) Aufruf entfernter Servermethoden 3) Starten des Klientenapplikationsobjekts 29 Schritte 1) & 2) class HelloClient { public static void main(String args []) throws Exception { ORB orb = ORB.init(args, null); NamingContextExt nameService = NamingContextExtHelper.narrow( orb.resolve_initial_references(”NameService”)); Hello server = HelloHelper.narrow( nameService.resolve_str(”HelloServer”)); String name = JOptionPane.showInputDialog( ”Who do you want to greet?”); if (name == null) { name = ””; } System.out.println(server.sayHello(name)); } } 30 3) Starten des Clientobjekts ‣ Analog zum Starten des Clientapplikationsobjekts $java HelloClient -ORBInitialPort 1050 31