CORBA – Common Object Request Broker Architecture

Transcription

CORBA – Common Object Request Broker Architecture
Vortrag: CORBA
Jörg Bogenrieder
CORBA – Common Object Request Broker Architecture
1. Einleitung
Moderne Programmiersprachen haben den objektorientierten Ansatz in die strukturierte
Berechnung in einem einzigen Betriebssystemprozess eingeführt. Der nächste logische
Schritt ist, die Verteilung der Berechnung über mehrere Prozesse auf eine oder auf
mehrere CPU´s. Da die Objektorientiertheit eine passende Methode zur Entwicklung und
zum Betrieb großer skalierbarer Applikationen liefert, liegt es auf der Hand, diesen Ansatz
auch zum Entwickeln von verteilten Anwendungen zu benutzen. Die Objekte sind auf
vielen Computern verteilt, die mit einem Netzwerk miteinander verbunden sind.
Leider ist es eine Tatsache, daß sich in einem Netzwerk, die Hardware, die Architektur
und die Betriebssysteme der einzelnene Systeme voneinander unterscheiden. Auch die
Programmiersprachen, in denen die Objekte implementiert wurden, sind verschieden.
Diese heterogenen verteilten Systeme benötigen für die Kommunikation der Objekte eine
sogenannte Middelware. Die Common Object Request Broker Architecture ist eine
Spezifikation einer solchen Middelware. CORBA ist ein offener Standard der von der
Object Management Group (OMG) betreut und stetig weiter entwickelt wird.
CORBA beinhaltet folgende Punkte:
Objektorientiertheit
Objekte sind die Grundbausteine von CORBA-Applikationen
Ortstransparenz
Ein Objekt wird immer mit den gleichen Mechanismen aufgerufen, egal ob es sich
im gleichen Adressbereich, im gleichen Computer oder in einem entfernten
Computer befindet.
Hardware-, Betriebssystem- und Sprachunabhängigkeit
CORBA Komponenten können in verschiedenen Programmiersprachen auf
verschiedenen Architekturen mit unterschiedlichen Betriebssystemen implementiert
werden.
Herstellerunabhängigkeit
Man ist nicht an ein Hersteller gebunden, da der CORBA Standard die
Kommunikation der Objekte festlegt. Daher können unterschiedliche ORB´s
eingesetzt werden.
2. IDL Interface Definition Language
Die Interface Definition Language dient zur Beschreibung der Schnittstellen (ähnlich einer
Headerdatei in C oder Schnittstellendefinition in C++), sie trennt die Implementierung und
die Schnittstellen eines Objektes. Der IDL-Code ist sehr stark an die C++ Syntax
angelehnt. Um aus der IDL-Datei nun den Code für die eigentliche Implementierung zu
erhalten, muss diese mittels eines IDL-Compilers in die jeweilige Sprache überführt
werden. Der Compiler erzeugt eine Anzahl von Dateien, die Stub und Hilfsklassen. Diese
Dateien dienen als Gerüst für die Verbindung zwischen den Objekten.
Seite 1 von 11
Vortrag: CORBA
Jörg Bogenrieder
3. Die CORBA Dienste
Bei CORBA hat die OMG 15 Objektdienst-Spezifikationen veröffentlicht. Diese Dienste
(CORBA-Services) dienen als Erweiterung und Ergänzung der Funktionalität eines ORBs.
Hiermit kann eine Komponente erzeugt, benannt und in die Umgebung eingebaut werden.
Life-Cycle-Service
definiert die Operationen für das Erzeugen, Kopieren, Verschieben und Löschen
von Komponenten.
Persistence-Service
bietet eine einheitliche Schnittstelle für das langfristige Speichern von
Komponenten
auf
einer
Vielzahl
von
Speicher-Servern
wie
z.B.
Objektdatenbanken, relationale Datenbanken oder Dateien.
Naming-Service
ermöglicht den Komponenten andere Komponenten über ihren Namen zu finden; er
unterstützt auch einen verteilten Namens-Dienst, also Namenskontexte, die sich in
unterschiedlichen ORB-Domänen befinden. Mit Hilfe dieses Dienstes lassen sich
Objekte in vorhandene Netzwerkverzeichnisse oder Namenskontexte einbinden,
z.B. NIS+ (Sun), NDS (Novell) oder LDAP (Internet).
Event-Service
ermöglicht den Komponenten ihr Interesse an bestimmten Ereignissen dynamisch
registrieren und deregistrieren zu lassen. Der Dienst definiert ein permanentes
Objekt, den Event Channel, der Ereignisse sammelt und an Komponenten verteilt,
die nichts voneinander wissen.
Concurrent-Control-Service
bietet einen Lock-Manager, der im Auftrag von Transaktionen oder Threads
Sperrungen vornehmen kann.
Transaction-Service
sorgt für die Koordinierung eines zweiphasigen Bestätigungsprotokolls (two-phase
commit) zwischen wiederherstellbaren Komponenten, die flach oder verschachtelte
Transaktionen verwenden.
Relationship-Service
bietet die Möglichkeit, dynamische Assoziationen (oder Verknüpfungen) zwischen
Komponenten zu erzeugen, die voneinander nichts wissen. Er stellt ach
Mechanismen zum Durchqueren dieser Verknüpfungen zur Verfügung, die die
Komponenten gruppieren. Mit Hilfe diese Dienstes können Bedingungen für
referentielle Integrität erzwungen werden, Beziehungen zwischen den Inhalten
verfolgt und beliebige Arten von Verknüpfungen zwischen den Komponenten
vorgenommen werden.
Externalisation-Service
ist eine Standardmethode, über einen Stream-Mechanismus Daten in eine
Komponente hinein zu importieren und aus ihr heraus zu exportieren.
Query-Service
stellt Abfrageoperationen für Objekte bereit. Er bildet eine Erweiterung von SQL auf
Basis der SQL3-Spezifikation und der Object Query Language (OQL) der Object
Database Management Group (ODMG).
Seite 2 von 11
Vortrag: CORBA
Jörg Bogenrieder
Licensing-Service
bietet Operationen, um für eine faire Abrechnung die Nutzungsdauer von
Komponenten zu messen. Der Dienst unterstützt beliebige Modelle der
Nutzungkontrolle zu jedem Zeitpunkt im Lebenszyklus einer Komponente, z.B.
Berechnung pro Sitzung, pro Knoten, pro Instanz oder pro Site.
Properties-Service
bietet Operationen, um Namen/Werte-Paare mit beliebigen Komponenten zu
assoziieren. Mit Hilfe dieses Dienstes lassen sich dynamisch einer Komponente
Eigenschaften zuweisen, z.B. ein Titel oder ein Datum.
Time-Service
stellt eine Schnittstelle zur Uhrzeitsynchronisation in einer verteilten
Objektumgebung zur Verfügung. Er bietet auch Operationen für die Definition und
Verwaltung von zeitgetriggerten Ereignissen.
Security-Service
liefert ein komplettes Framework für die Sicherheit bei verteilten Objekten. Er
unterstützt
Identifizierung,
Zugriffskontrollisten,
Vertraulichkeit
und
Unwiderlegbarkeit. Er verwaltet auch die Delegierung von „Ausweisen“ zwischen
Objekten.
Trader-Service
stellt die „gelben Seiten“ für Objekte bereit. Er erlaubt Objekten ihre Dienste
anzubieten, oder nach bestimmten Diensten zu suchen.
Collection-Service
ermöglicht es CORBA-Schnittstellen, allgemeine Collections zu erzeugen und zu
manipulieren.
4. Wie initialisiert der Client die Server Objekte?
Da es bei CORBA keine explizite Methode für einen Client gibt, die ein Server-Objekt
aktiviert, muss dies von der Serverseite aus bewerkstelligt werden. Natürlich werden nicht
alle Objekte beim Start des Servers explizit gestartet, sondern es wird nur der Eindruck
erweckt, daß das Server-Objekt geladen und aktiv ist. Diese Aufgabe übernimmt auf der
Serverseite der Basic Object Adapter (BOA). Er wird verwendet um Objektreferenzen zu
erzeugen oder zu löschen und um Informationen der Objektreferenz abzufragen und zu
ändern. Der BOA verwaltet ein Verzeichnis aller aktiven Objekte und Implementierungen.
Die BOA-Schnittstelle wird dazu verwendet um mit diesem Verzeichnis zu kommunizieren
und dem ORB von den Objekten zu berichten. Es lässt sich als Zusammenarbeit
zwischen dem Server-Objekt und dem ORB vorstellen, um so für die Illusion zu sorgen,
daß alle Server-Objekte immer aktiv sind.
5. Erste Schritte mit CORBA oder wie erreiche ich meinen ORB?
Ein ORB ist eigentlich nichts anderes als eine Objektbibliothek, die je nach
Sprachbindung des ORBs in den jeweiligen Sprachen vorhanden sind und in das
CORBA-Programm eingebunden werden (ähnlich wie bei RPC). Die CORBA-Spezifikation
legt fest, wie die einzelnen Objekte aufgerufen werden und welche Methoden sie zu
Verfügung stellen. Um ein ORB einzusetzen genügt es, in seinem Programm eine
Referenz auf des ORB-Objekt anzulegen, nun läßt sich der ORB ansprechen.
Seite 3 von 11
Vortrag: CORBA
Jörg Bogenrieder
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
liefert die Referenz auf das ORB-Objekt. Mit
orb.list_initial_services();
lassen sich alle Dienste auflisten, die der ORB zu bieten hat. Mit
org.omg.CORBA.Object objPoa = null;
objPoa = orb.resolve_initial_references("<Name des Dienstes>");
wird der Name des Dienstes in eine Objektreferenz umgewandelt und kann nun
angesprochen werden.
6. Jetzt wird’s ernst!
Um die Mechanismen genauer zu beleuchten wird es Zeit für unser allseits beliebtes
HelloWorld Beispiel. Als ORB dient uns JavaORB, ein frei verfügbarer ORB mit Java als
Sprachbindung, in der Version 2.2.7.
Dazu benötigen wir unsere IDL Datei. Sie beinhaltet folgenden Code:
interface HelloWorld {
string sayHello();
};
Bei IDL ist darauf zu achten, daß nach der letzten geschweiften Klammer ebenfalls ein
Strichpunkt sein muss.
Nun wird mit Hilfe des IDL-Compilers unsere Stub und Hilfsklassen erzeugt. Der Aufruf
lautet:
idl2java <IDL-Datei> [-Options]
Der IDL-Compiler erzeugt nun folgende Dateien:
HelloWorld.java
HelloWorldHelper.java
HelloWorldHolder.java
HelloWorldOperations.java
_HelloWorldImplBase.java
_HelloWorldStub.java
Diese Dateien befinden sich nun in dem Verzeichnis ./corba_pkg/ . Nun muss nur noch
der Clientcode, der Servercode und die Implementierung der Schnittstelle HelloWorld
geschrieben werden.
7. Implementierung der Schnittstelle:
Hierzu muss eine Klasse von der Klasse _HelloWorldImpleBase abgeleitet werden und
die Funktionalität des Programms implementiert werden. Bei uns soll mittels
getLocalHost() der Name und die IP-Adresse des Host zurückgegeben werden, auf dem
sich das Objekt befindet.
8. Implementierung des Client:
Zuerst brauchen wir eine Referenz auf unsern ORB, diese wird mittels
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
hergestellt.
Seite 4 von 11
Vortrag: CORBA
Jörg Bogenrieder
Um den ORB zu befragen wo sich das Serverobjekt befindet, bedienen wir uns des
Name-Service, hierzu benötigen wir eine Objektreferenz zu einem Name-ServiceObjektes - dies wird hiermit hergestellt.
org.omg.CORBA.Object obj = null;
org.omg.CosNaming.NamingContext naming = null;
try
{
obj = orb.resolve_initial_references( "NameService" );
naming = org.omg.CosNaming.NamingContextHelper.narrow( obj );
}
mit der Methode narrow() wird ein Downcast eines CORBA.Object zu NaimingContext
durchgeführt. Nun sind wir mit dem Name-Service unseres ORB verbunden. Um den Pfad
zu unserem Objekt zu finden wird zuerst eine Anfrage an den Name-Service
zusammengestellt.
org.omg.CosNaming.NameComponent[] name = new
org.omg.CosNaming.NameComponent[1];
name[0] = new org.omg.CosNaming.NameComponent();
name[0].id = "HelloWorld";
name[0].kind = "Example";
und mit
obj = naming.resolve(name);
an den Name-Service geschickt. Mittels
HelloWorld hello = HelloWorldHelper.narrow( obj );
wird unsere Objektreferenz wieder Downgecastet. Und über
hello.sayHello();
wird unser Objekt angesprochen.
9. Nun geht’s an den Server:
Auch unsere Serverklasse benötigt zuerst eine Referenz auf den ORB dies wird genau
wie beim Client erledigt. Danach wird eine Referenz auf den BOA hergestellt.
org.omg.CORBA.BOA boa = org.omg.CORBA.BOA.init(orb,args);
Danach wird eine Instanz unserer Schnittstellenimplementierung HelloWorldImpl gebildet
und beim BOA registriert und aktiviert (nochmals zur Erinnerung, das Objekt wird nicht
wirklich gestartet, sondern erst wenn eine Anfrage vom Client kommt)
HelloWorldImpl hello = new HelloWorldImpl();
boa.connect(hello);
boa.obj_is_ready(hello);
Danach benötigen wir wieder eine Objektreferenz auf ein Name-Service Objekt dies wird
genauso hergestellt wie beim Client. Wenn wir diese Objektreferenz haben, wird unser
Objekt in den Name-Service eingetragen
org.omg.CosNaming.NameComponent [] name = new
org.omg.CosNaming.NameComponent[1];
name[0] = new org.omg.CosNaming.NameComponent();
name[0].id = "HelloWorld";
name[0].kind = "Example";
naming.bind(name,hello);
Seite 5 von 11
Vortrag: CORBA
Jörg Bogenrieder
Was nun noch übrig bleibt ist, daß wir unser Serverobjekt beim BOA anmelden und auf
eingehende Anfragen warten. Wir starten den Name-Service und unser Serverobjekt
durch
naming
java <Name des Serverprogramms>
Nun beantwortet der Server die Anfrage des Clients.
Seite 6 von 11
Vortrag: CORBA
Jörg Bogenrieder
Quellenangabe:
Instant CORBA: Führung durch die CORBA-Welt
Robert Orfali, Dan Harky, Jeri Edwards; Bonn: Addison Wesly Longman GmbH
ISBN 3-8273-1325-2
Java Programming with CORBA
Andreas Vogel, Keith Duddy; New York: Wiley Computer Publishing
ISBN 0-471-17986-8
CORE Java 2 - Expertenwissen
Cay S. Horstmann, Gary Cornell; München: Markt + Technik Verlag
ISBN 3-8272-9566-1
Internet:
Object Management Groupe: www.omg.org
JavaOrb: www.multimania.com/dogweb, dog.exoffice.com
Quelltexte:
/******************************************************************/
/*
*/
/* The Server of Hello World Program
*/
/* using the NamingService
*/
/*
*/
/* @author Joerg Bogenrieder
*/
/* @version 0.0.1
*/
/*
*/
/******************************************************************/
public class Server_name
{
public static void main( String args[] )
{
// 1.
// Initialize the ORB
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args,null);
// 2.
// Initialize the BOA
org.omg.CORBA.BOA boa = org.omg.CORBA.BOA.init(orb,args);
// 3.
// Instanciate Calculator object
HelloWorldImpl hello = new HelloWorldImpl();
// 4.
// Connect the instance to BOA
boa.connect(hello);
// 5.
// Activate the instance
boa.obj_is_ready(hello);
Seite 7 von 11
Vortrag: CORBA
Jörg Bogenrieder
// 6.
// Resolve the NameService
org.omg.CORBA.Object obj = null;
org.omg.CosNaming.NamingContextExt naming = null;
try
{
obj = orb.resolve_initial_references("NameService");
naming = org.omg.CosNaming.NamingContextExtHelper.narrow(obj);
}
catch ( org.omg.CORBA.ORBPackage.InvalidName name )
{
System.out.println("Enable to resolve NameService");
System.exit(0);
}
if ( naming == null )
{
System.out.println("The NameService was not found");
System.exit(0);
}
// 7.
// Build HelloWorld path
org.omg.CosNaming.NameComponent [] name = new
org.omg.CosNaming.NameComponent[1];
name[0] = new org.omg.CosNaming.NameComponent();
name[0].id = "HelloWorld";
name[0].kind = "Example";
// 8.
// Bind Calculator into NameService
try
{
naming.bind(name,hello);
}
catch( org.omg.CosNaming.NamingContextPackage.NotFound ex )
{
System.out.println("Object not found");
System.exit(0);
}
catch( org.omg.CosNaming.NamingContextPackage.AlreadyBound ex )
{
System.out.println("Already bound");
System.exit(0);
}
catch( org.omg.CosNaming.NamingContextPackage.InvalidName ex )
{
System.out.println("Invalid name");
System.exit(0);
}
catch( org.omg.CosNaming.NamingContextPackage.CannotProceed ex )
{
System.out.println("Cannot proceed");
Seite 8 von 11
Vortrag: CORBA
Jörg Bogenrieder
System.exit(0);
}
// 9.
// Wait for invocations
try
{
System.out.println("The server is ready...");
boa.impl_is_ready();
}
catch( java.lang.Exception ex )
{
System.out.println("An exception has been intercepted.");
}
} // main
} // class
/******************************************************************/
/*
*/
/* The Implementation of Hello World Program
*/
/*
*/
/* @author Joerg Bogenrieder
*/
/* @version 0.0.1
*/
/*
*/
/******************************************************************/
public class HelloWorldImpl extends _HelloWorldImplBase
{
private String str;
public String sayHello()
{
try
{
java.net.InetAddress InetAddr =
java.net.InetAddress.getLocalHost();
str = InetAddr.toString();
}
catch( java.net.UnknownHostException exc )
{
System.out.println( exc.getMessage() );
}
str = str + " say: HelloWorld! to you";
return str;
} // sayHello
} // class
Seite 9 von 11
Vortrag: CORBA
Jörg Bogenrieder
/******************************************************************/
/*
*/
/* The Client of Hello World Program
*/
/* using the NamingService
*/
/*
*/
/* @author Joerg Bogenrieder
*/
/* @version 0.0.1
*/
/*
*/
/******************************************************************/
public class Client_name
{
public static void main( String args[] )
{
// 1.
// Initialize the ORB
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init( args, null );
// 2.
// Resolve the NamingService
org.omg.CORBA.Object obj = null;
org.omg.CosNaming.NamingContext naming = null;
try
{
obj = orb.resolve_initial_references( "NameService" );
naming = org.omg.CosNaming.NamingContextHelper.narrow( obj );
}
catch( org.omg.CORBA.ORBPackage.InvalidName name )
{
System.out.println( "Enable to resolve NameService" );
System.exit( 0 );
}
// 3.
// Build HelloWorld path
org.omg.CosNaming.NameComponent[] name = new
org.omg.CosNaming.NameComponent[1];
name[0] = new org.omg.CosNaming.NameComponent();
name[0].id = "HelloWorld";
name[0].kind = "Example";
// 4.
// Resolve Calculator reference from NamingService
try
{
obj = naming.resolve(name);
}
catch( org.omg.CosNaming.NamingContextPackage.NotFound ex )
{
System.out.println("Object not found");
System.exit(0);
}
catch(org.omg.CosNaming.NamingContextPackage.CannotProceed ex)
Seite 10 von 11
Vortrag: CORBA
Jörg Bogenrieder
{
System.out.println("Cannot proceed");
System.exit(0);
}
catch( org.omg.CosNaming.NamingContextPackage.InvalidName ex )
{
System.out.println("Invalid name");
System.exit(0);
}
// 5.
// Narrow the Object referece
HelloWorld hello = HelloWorldHelper.narrow( obj );
// 6.
// Use the Hello World Object
try
{
String tmp = hello.sayHello();
System.out.println( "Host: " + tmp );
}
catch( org.omg.CORBA.SystemException exc )
{
System.out.println( "A CORBA System exception?" );
System.out.println( exc.getMessage() );
}
} // main
} // class
Seite 11 von 11