8. CORBA (Teodora Guenkova-Luy) 8.1 Einführung 8.1.1 Das Problem - Heterogenität Hardware Plattformen Betriebssysteme Netzwerkprotokolle Anwendungsformate Programmiersprachen Die Netzwerke bestehen nicht nur aus dem Internet und die Geräte sind nicht nur PCs. Inzwischen sind die Netzwerke auch mobil und es gibt größere Anforderungen an Echtzeit. Und das alles muß mit alten, schon existierenden Anwendungen kompatibel sein. Existierende Werkzeuge ? - Die existierenden Werkzeuge (Sockets, - DCE - Distributed Computing Environment) funktionieren nur auf den niederen Ebenen des Protokollstacks Sie bieten keine gleichartige Sicht auf alle verteilten Anwendungen Die Komplexität verteilter Systeme wächst stetig Wachsender Implementierungs- und Management-Aufwand 8.2 Object Management Group (OMG) Die Vision: “Die Erstellung einer Gesamtarchitektur, in der verschiedene Softwarekomponenten möglichst transparent und in heterogenen Umgebung miteinander kommunizieren können.” Das Geschäftsmodell: - Jedes Programm ist ein Modell eines Teils des Gesamtunternehmens – Forschung, - Herstellung, Verkauf, Versand, Rechnungswesen, Finanzen, etc. Die Einzelteile sollen zusammenarbeiten, dabei wird Objekttechnologie verwendet Die Organisation (www.omg.org): Mehr als 800 Industrieunternehmen Verwirklichung der Vision und des Geschäftsmodells Entwicklung von Spezifikationen und Standards - OMA – Object Management Architecture - CORBA – Common Object Request Broker Architecture - UML – Unified Modeling Language - MOF – Meta-Object Facility - XMI – XML Metadata Interchange 8.3 Open Management Architecture (OMA) Anwendungsspezifisch Spezifische, branchenabhängige Dienste Domain Interfaces (Vertical CORBA Facilities) Application Objects Object Request Broker CORBA Services Fundamentale Dienste, die von allen Objekten benutzt werden können Common Facilities (Horizontal CORBA Facilities) Allgemeine Verwaltungsdienste CORBA Services - Collection Service Concurrency Service Enhanced View of Time Event Service Externalization Service Naming Service Licensing Service Life Cycle Service Notification Service - Persistent Object Service Property Service Query Service Relationship Service Security Service Time Service Trading Object Service Transaction Service Common Facilities - Business Object Facility Data Interchange Facility Distributed Document Component Facility Meta-Object Facility Mobile Agent Facility Printing Facility System Management Facility Domain Interfaces - Product Data Management Enablers - Healthcare Patient Lexicon Service - 8.4 CORBA Architektur 8.4.1 Die Clientseite Enthält die Beschreibungen aller registrierten Objekte (Schnittstellen) Datenbank Client-Objekt Eindeutige Identifikation - Eine Art Name und Adresse des Servers, die der eindeutigen Referenzierung dient Repräsentant des Servers auf der Clientseite Dynamic Invocation Interface - Generiert Nachrichten, die das Format (die Schnittstelle) eines Objekts beschreiben Nachfrage (Schnittstellen Beschreibung), ob es ein vom Client gewünschtes Objekt schon irgendwo gibt 8.4.2 Die Serverseite Namensdienst Verwaltet die Server-Objekt-Instanzen und - Referenzen Dynamic Server Interface - Entspricht dem DII auf der Serverseite Dient der dynamischen Herstellung der Verbindung zum ORB, ohne Skeleton Server-Objekt BOA (Basic Object Adapter) POA (Portable Object Adapter) Repräsentant des Clients auf die Serverseite - Verwaltet die ORB-Aufrufe Startet und instanziiert die Implementierungsobjekte Registriert die von Ihm unterstützten Klassen Vergibt die Eindeutigen Objektreferenzen BOA – ORB Implementierungsspezifisch POA Portabel zwischen verschiedenen ORBImplementierungen 8.4.3 Der Broker Standard Interface des Brokers Definition aller Interfaces der CORBA Standard Dienste Standard Protokol des Brokers Object Request Broker - Enthält die von OMG definierten Dienste - Alle Objekte verbinden sich zum ORB über das standardisierte Interface Kann unterschiedlich implementiert werden, u. a. Bibliotheken, DaemonMechanismen, zentralisierte Server, etc. 8.4.4 Die Objektreferenzen; Mitteilung der Referenzen IOR – Interoperable Object Reference IOR ist eine Datenstruktur – enthält Informationen über den Typ des ORBs, die unterstützten Protokolle und die vorhandenen Dienste im ORB. - Wird durch den ORB jedem neuen Server-Objekt(Servant) zugeteilt Muß global eindeutig sein Die Referenz ist so lange gültig wie das Objekt existiert Referenz im CORBA Name Service eingetragen und so für die Clients bekannt gemacht Der Client benutzt einen ihm bekannte Name des Namensdienstes, um bei ihm nach den Referenzen der vom Server verwalteten Server-Objekte anzufragen. Beispiel: URL IOR 8.4.5 CORBA Aufrufe statisch BOA statisch POA Dynamisch BOA oder POA - BOA - beim statischen Aufrufen innerhalb eines spezifischen ORBs (verkürzte form der IOR) - POA - beim statischen Aufrufen innerhalb ORBs verschiedener Hersteller (vollständiger IOR) 8.4.6 Statische Aufrufe 8.4.7 Statische Aufrufe (Fortsetzung) - Die Referenz des Objekts wird bekannt gemacht Der Client erfährt die Referenz Der Stub verpackt die Parameter in geeigneter Form (Marshalling) Aufruf des ORBs und übertragen der Parameter Der Objekt Adapter aktiviert das Objekt, eventuell wird neue Instanz des Objekts erzeugt, und übergibt die Parameter dem Skeleton Das Skeleton entpackt die Parameter (Demarshalling) und übergibt sie dem Objekt Statischer Aufruf - Serverseite //Erzeugt die Verbindung zum ORB ORB orb = ORB.init(args, null); //Der Servant Objekt wird erzeugt und an ORB angebunden HelloServant helloRef = new HelloServant(); orb.connect(helloRef); // Verbindung zum Namensdienst org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); //Mitteilung der Referenz des Objekts NameComponent nc = new NameComponent("Hello", ""); NameComponent path[ ] = {nc}; ncRef.rebind(path, helloRef); // Warten auf Clienten-Aufrufe java.lang.Object sync = new java.lang.Object(); Das Servant-Objekt class HelloServant extends _HelloImplBase { public String sayHello() { return "\nHello world!!\n"; } } Statischer Aufruf - Clientseite //Erzeugt die Verbindung zum ORB ORB orb = ORB.init(args, null); // Verbindung zum Namensdienst org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); //Erfahren der Referenz des Objekts NameComponent nc = new NameComponent("Hello", ""); NameComponent path[ ] = {nc}; Hello helloRef = HelloHelper.narrow(ncRef.resolve(path)); // Aufruf des Hallo-Servers und Ergebnis ausdrucken String hello = helloRef.sayHello(); System.out.println(hello); 8.4.8 Dynamische Aufrufe 8.4.9 Dynamische Aufrufe (Fortsetzung) - Die Referenz, die Implementierung und das Standard-Interface des Objekts werden bekannt - gemacht Der Client erfährt die Referenz Der Client startet eine Anfrage an DII mit der Referenz und seiner Vorstellung der Schnittstelle DII macht Anfrage beim Interface Repository, ob es das nachgefragte Interface schon gibt, holt es, erzeugt Client-Stub und benutzt den Stub für Marshalling Aufruf des ORBs und Übertragen der Parameter Der POA fragt beim Implementation Repository, ob das angefragte Objekt existiert, holt es, aktiviert es und erzeugt eine Instanz davon POA übergibt an DSI das Standard Interface des Objekts und die Client-Parameter zum Demarshalling DSI erzeugt Server-Skeleton, benutzt ihn zum Demarshalling und übergibt die Parameter dem gestarteten Objekt. Dynamischer Aufruf - Serverseite // Erzeugt die Verbindung zum ORB org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); //Erzeugt die Verbindung zum POA POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); POAManager poaManager = rootPOA.the_POAManager(); //Verbindungseinstellungen des Servers org.omg.CORBA.Policy[ ] managerPolicies = { rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT), rootPOA.create_request_processing_policy (RequestProcessingPolicyValue.USE_DEFAULT_SERVANT), rootPOA.create_id_uniqueness_policy (IdUniquenessPolicyValue.MULTIPLE_ID) }; Dynamischer Aufruf – Serverseite (Fortsetzung) //Verbinden des Servers zum POA POA helloPOA = rootPOA.create_POA("hello_poa", poaManager, helloPolicies); //Das Servant-Objekt wird erzeugt und bekannt gemacht HelloServant helloServant = new HelloServant (orb, helloPOA); helloPOA.set_servant(helloServant); // Aktivieren des POA Managers poaManager.activate(); // Warten auf Client-Aufrufe orb.run(); Dynamischer Aufruf – Das Servant-Objekt public class HelloServant extends DynamicImplementation { //Der Name des CORBA Interfaces als ID public static final String[ ] ids = new String[] { "IDL:HelloApp:1.0" }; // Referenzen zum ORB und POA public HelloServant (org.omg.CORBA.ORB orb, POA poa) { _orb = orb; _poa = poa; } //Methode zum Herausfinden des Objekts public synchronized org.omg.CORBA.Object get(String name) { //Das Objekt ist am Anfang unbekant org.omg.CORBA.Object obj; // Überprüfen, ob es so ein Objekt schon gibt String helloObj = (String)_registry.get(name); //Schreiben des Objects if (helloObj == null) { _registry.put(name, “Hello world!”); } Dynamischer Aufruf – Das Servant-Objekt (Fortsetzung) // Bekanntgeben der Referenz des Objekts byte[ ] hellotId = name.getBytes(); try { obj = _poa.create_reference_with_id(helloId, ids[0]); } catch (org.omg.PortableServer.POAPackage.WrongPolicy e) { throw new org.omg.CORBA.INTERNAL(e.toString()); } return obj; }//Ende der Methode zum Herausfinden des Objekts //Methode zum Herausfinden des richtigen Interfaces public String[] _all_interfaces(POA poa, byte[ ] objectId) { return ids; } //Methode zum Starten und Benutzen des Servant-Objekts public void invoke(org.omg.CORBA.ServerRequest request) { //Das Ergebnisobjekt String helloObj; Dynamischer Aufruf – Das Servant-Objekt (Fortsetzung) // Objektesname des helloObj String name = new String(_object_id()); // Sicherstellen, daß der aufgerufene Methodenname korrekt ist if (!request.operation().equals("sayHello")) { throw new org.omg.CORBA.BAD_OPERATION(); } // Einlesen des eingeschriebenen Objekts und Übergabe des Objekts org.omg.CORBA.NVList params = _orb.create_list(0); request.arguments(params); helloObj = (String)_registry.get(name); if (helloObj == null) { hrow new org.omg.CORBA.OBJECT_NOT_EXIST(); } org.omg.CORBA.Any result = _orb.create_any(); result.insert_string(hello.stringValue()); request.set_result(result); } //Ende der Methode zum Starten und Benutzen des Servant-Objekts Dynamischer Aufruf – Das Client-Objekt // Erzeugt die Verbindung zum ORB org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); // Referenz des Manager Objekts byte[ ] managerId = "HelloAppManager".getBytes();//Der Name wird vom Namen des IDLs erzeugt // Herausfinden des Manager Objekts org.omg.CORBA.Object manager = ((com.inprise.vbroker.orb.ORB)orb).bind("/hello_poa", managerId, null, null); // Dynamischer Aufruf der Methode org.omg.CORBA.Request request = manager._request("sayHello"); // Typ des Ergebnisses request.set_return_type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_string)); // Holen des Ergebnisses request.invoke(); // Endergebnis und Anzeige String hello; org.omg.CORBA.Any hello_result = request.return_value(); hello = hello_result.extract_string(); System.out.println (hello); 8.5 Werkzeuge der Interoperabilität 8.5.1 IDL – Interface Definition Language IDL definiert die Signatur des Interfaces zwischen dem Client und dem Server - Standard Typen Standard Typen der Variablen Standard Rückgabetypen Standard Typen bei Ausnahmezuständen (CORBA Exceptions) - Standard Module und CORBA Objekte IDL-Beispiel: Plattformunabhängigkeit (z.B. NT, Unix) module HelloApp { interface Hello { Unabhängig von einer spezifischen Sprache bzw. Compiler string sayHello(); Bindungen für viele Sprachen/Compiler (language mappings) – C, C++, Java, Ada, COBOL, Smalltalk, etc. }; Keine Programmiersprache – dient nur der Beschreibung }; CORBA Typen und Mapping - Einfache Typen CORBA boolean char wchar Java boolean char char C++ CORBA::Boolean CORBA::Char CORBA::WChar octet string wstring byte java.lang.String java.lang.String CORBA::Octet short unsigned short long unsigned long longlong unsigned longlong float double short short int int long long CORBA::Short CORBA::UShort CORBA::Long CORBA::ULong CORBA::LongLong CORBA::ULongLong unsigned char char NICHT IMPLEMENTIERT unsigned char char * NICHT IMPLEMENTIERT short unsigned short PLATTFORMABHÄNGIG unsigned long PLATTFORMABHÄNGIG PLATTFORMABHÄNGIG float double CORBA::Float CORBA::Double float double - Komplexe Typen CORBA enum struct union sequence (mit typedef) array (mit typedef) Java Java final class Java final class Java final class Java array C++ enum struct & _var class struct & _var class struct & _var class Java array exception any typedef Java class / Java final class Java class Wird gemapped nur zusammen mit anderen Typen interface + stub- & skeletonclasses package array, array_slice, array_forany, & array_var C++ class C++ class typedef interface module C++ class + stub- & skeletonclasses Class/C++ Library (*.h; *.hh) - Beispiele für komplexe Typen: struct ID{ long userID; long sessionID; long streamID; long flowID; };- Besondere Typen typedef sequence<string> URLs; exception InvalidID {}; CORBA In Java Java parameter (functions) out Java parameter (functions) + additional holder classes Java parameter (functions) + additional holder classes holder classes inout oneway valuetype C++ own C++ types & member functions own C++ types & member functions Bedeutung Übergabeparameter vom Client zum Server own C++ types & member functions Übergabeparameter vom Client zum Server und ungekehrt Übergabeparameter vom Server zum Client CORBA hat per Annahme “at-most-once”-Semantik für die Nachrichtenübertragung, “oneway” definiert explizit “best-effort”-Semantik und wird für asynchronen Nachrichtenaustausch benuzt CORBA unterstützt per Annahme “object-by-reference” Übertragung, “valuetype“ definiert explizit “object-byvalue” Übertragung - Beispiele für besondere Typen: valuetype StringValue string; interface ORBOnewaySlider { oneway void SliderPositions(in long pos1, in long pos2); }; Interface Compiler - Die Interface Compiler dienen der Übersetzung des IDL-Interfaces in einer bestimmten Programmiersprache. - Es gibt unterschiedliche Compiler von verschiedenen Herstellern: - JDK1.3 von SUN – idlj (Java spezifische Stub und Skeleton nur für statische Aufrufe) VisiBroker von Inprise idl2java - Java spezifische Stub und Skeleton für statische Aufrufe mit Benutzung von POA idl2cpp - C++ spezifische Stub und Skeleton für statische Aufrufe mit Benutzung von POA idl2ir – wird benutzt im Zusammenhang mit der „Interface Repository“ für dynamische Aufrufe Bedeutung der erzeugten Klassen - Client Stub – Marshalling (Name des definierten Interfaces + “Stub”, z.B. “HelloStub.java” ) - Server Skeleton – Demarshalling (Name des definierten Interfaces + “ImplBase”, z.B. “HelloImplBase.java”) - Helper-, Holder- und Tie- Klassen dienen der Abbildung der - programmiersprachenspezifischen Übertragungsmechanismen in CORBA-spezifische Mechanismen. Das ist verbunden mit der Übertragung der Daten-Typen und mit den Speicher-Abbildungen, sowie mit ORB-spezifischen Aufrufen. z.B. Java unterstützt „object-by-value“ Übertragungsmechanismus und CORBA „object-byreference“; bei Rückgabeparameter (out- und inoutParameter) vom Server zum Client dient die Holder-Klasse dieser Abbildung. Abhängigkeit der erzeugten Klassen interface HelloOperations Verwendung abstract class HelloHelper Vererbung interface Hello class HelloHolder Implementierung class HelloStub Clientseite abstract class HelloImplBase Serverseite Abhängigkeit der erzeugten Klassen (Fortsetzung) final class HelloHelper interface HelloOperations Komponente class HelloHolder interface Hello class HelloStub interface HelloPOA class HelloPOATie Abhängigkeit der erzeugten Klassen (Fortsetzung) idlj – Compiler idl2java – Compiler Java Interfaces: Hello.java HelloOperations.java Java Interfaces: Hello.java HelloOperations.java Server Skeleton: HelloImplBase.java POA Klassen statt Server Skeleton: HelloPOA.java HelloPOATie.java Client Stub: HelloStub.java Client Stub: HelloStub.java Helper und Holder: HelloHelper.java HelloHolder.java Helper und Holder: HelloHelper.java HelloHolder.java 8.5.2 Das Protokoll GIOP und ESIOP GIOP – General Inter-ORB Protocol – GIOP zwingend um CORBA 2 konform zu sein ESIOP – Environment Specific Inter-ORB Protocol – DCE ESIOP ist optional. GIOP OSI vs. GIOP GIOP (Fortsetzung) GIOP ist die Abbildung auf schon existierende Protokolle und die Beschreibung, wie zwischen verschiedenen Protokollen übersetzt wird. GIOP beinhaltet CDR (Common Data Representation). CDR ist das Transferformat für die Daten-Typen: - zwischen verschiedenen Protokollen - zwischen verschiedenen Programmiersprachen - zwischen verschiedenen Plattformen Der CDR Transfersyntax: - Mapping der IDL Datentypen in eine bi-kanonische low-level Repräsentation - unterstützt variable Byteordnung und Alignment primitiver Typen z.B. 0x47 0x49 0x4f 0x50 GIOP Schlüssel 0x01 0x00 GIOP Version IIOP IIOP – Internet Inter-ORB Protocol IIOP ist eine Spezifikation der GIOP Semantik für TCP/IP Verbindungsmanagement verfügbar in allen CORBA 2 ORBs auch in vielen anderen Anwendungen, z.B. - Netscape Navigator (enthält VisiBroker) - viele Application-Server (z.B. BEA Weblogic) 8.6 CORBA und die klassischen Probleme der Verteilten Systeme 8.6.1 Limitierungen Standard CORBA „kümmert“ sich im allgemeinen nicht um klassische VSProbleme wie z.B.: - Latenz - Konsistenz - Fehlertoleranz - Kausale Ordnungen - Deadlock-Behandlung - Synchronisation CORBA bietet nur bestimmte Mechanismen, wie diese Probleme behandelt werden können, z.B. für Unterstützung der Konsistenz können „object-byvalue“ und „object-by-references“ Übertragungsmechanismen benutzt werden. Wie die Lösung aussieht, hängt aber von dem Programmierer ab. 8.6.2 Limitierungen (Fortsetzung) - Die meisten ORBs unterstützen nur folgende Semantik: Objektreferenzen werden per Referenz (by reference) übergeben „struct“-s und „union“-s werden per Wert (by value)übergeben „object-by-value“ muß von Hand durch Factories nachgebildet werden Die ORB Implementierungen sind nicht immer vollständig. 8.6.3 Performance Einschränkungen Leistung ist eingeschränkt gegenüber „von-Hand-Programmierung“ wegen: - zusätzliche Aufrufe zur Namensauflösung - Marshalling/Demarshalling Overhead - zusätzliche Datenkopien und Speichermanagement - Endpunkt- und Aufruf-Demultiplexing - Kontextwechsel und Synchronisations-Overhead - Kompromiß zwischen Performance und Erweiterbarkeit, Robustheit, Wartbarkeit 8.6.4 Eignung CORBA eignet sich für Adaptierung schon existierender Anwendungen. Da CORBA kein Betriebssystem Heterogenität ist, haben CORBALösungen nur Sinn unter den Umständen eines Kontexts, z.B. die Finanzoperationen einer Firma. Durch CORBA lassen sich alte und neue Anwendungen verknüpfen. CORBA ist ein Mittel zur einfachen Programmierung interoperabler Anwendungen in heterogener Umgebung. 8.6.5 CORBA 3 - Verbesserte Java und Internet-Integration Java-to-IDL Reverse Mapping Firewall Spezifikation CORBA Object URLs Quality of Service Control Asynchrone Aufrufe, asynchrones Messaging Invocation QoS Control Real-time, Minimum, Fault Tolerance CORBA Component-Model - Object by Value Übergabemechanismus - Component Container (Transaktionell, Persistent, Sicher) - Auslieferungsformat - Scriptsprache zur Anpassung der Komponenten Real-Time CORBA Real-Time CORBA 8.7 Literaturquellen OMG Homepage: http://www.omg.org/ CORBA Homepage: http://www.corba.com/ Inprise Corporation VisiBroker: http://www.borland.com/bes/visibroker/ oder http://www.inprise.com/bes/visibroker/ Java Tutorial: http://java.sun.com/docs/books/tutorial/ Weber M., „Verteilte Systeme“, Spektrum,1998 Boger M., „Java in verteilten Systeme“, dpunkt.verlag GmbH, 1999