20.01.2015 Aufrufe

Middleware-Konzepte Entfernte Aufrufe

Middleware-Konzepte Entfernte Aufrufe

Middleware-Konzepte Entfernte Aufrufe

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Middleware</strong>-<strong>Konzepte</strong><br />

<strong>Entfernte</strong> <strong>Aufrufe</strong><br />

Dr. Gero Mühl<br />

Kommunikations- und Betriebssysteme<br />

Fakultät für Elektrotechnik und Informatik<br />

Technische Universität Berlin


Übersicht<br />

> Remote Procedure Call (RPC)<br />

> Remote Method Invocation (RMI)<br />

> Common Request Broker Architecture (CORBA)<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 2


Remote Procedure Call (RPC)


Remote Procedure Call (RPC)<br />

> Aufruf einer nicht-lokalen Prozedur entfernter Aufruf<br />

> Transparent für aufrufende und aufgerufene Prozedur<br />

> Wirkt für <strong>Aufrufe</strong>nden wie ein lokaler Aufruf Blockierung<br />

> Bekanntes, bewährtes und bequemes<br />

Programmierparadigma<br />

> Verbirgt Verteilung und Netzkomplexität<br />

> Kein händisches Festlegen von Nachrichtentypen und -inhalt<br />

> Kein händisches Verpacken/Auspacken der Parameter<br />

> Kein händischen Senden/Empfangen von Nachrichten<br />

> …<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 4


Lokaler Prozeduraufruf<br />

<strong>Aufrufe</strong>nde Prozedur<br />

Aufgerufene Prozedur<br />

P(x,y,z)<br />

1<br />

2<br />

P(a,b,c)<br />

4<br />

3<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 5


Lokaler Prozeduraufruf<br />

> Prozedur<br />

> ist eine Menge von Instruktionen mit eindeutigem Namen<br />

> besteht aus Prozedurkopf und Prozedurrumpf<br />

> definiert lokale Variablen<br />

> ist gedächtnislos<br />

> kennt den <strong>Aufrufe</strong>nden nicht<br />

> Prozeduraufruf<br />

> ist Sprunganweisung mit Prozedurnamen und Prozedurparametern (In/Out)<br />

> alternativ zu Ausgabeparametern Rückgabe eines Wertes durch<br />

return-Anweisung<br />

> aufrufende Prozedur wird blockiert, bis aufgerufene Prozedur returniert<br />

> <strong>Aufrufe</strong>nde und aufgerufene Prozedur laufen in einem Adressraum<br />

⇒ Datenaustausch über globale Variablen ist möglich und kann<br />

(unerwünschte) Seiteneffekte verursachen (möglichst) vermeiden<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 6


Prozedurparameter<br />

> Verschiedene Übergabearten möglich<br />

> call-by value, call-by reference, call-by copy/restore<br />

> Prozedurdefinition enthält die formalen Parameter<br />

> Namen, Typen, Übergabeart<br />

> Beim Aufruf werden die tatsächlichen Parameter übergeben<br />

> Compiler prüft Typkonformität<br />

PROCEDURE quadrat ( x REAL, VAR ergebnis REAL );<br />

VAR i: INT;<br />

BEGIN<br />

i := x * x;<br />

ergebnis := i;<br />

END quadrat;<br />

by value by reference<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 7


Remote Procedure Call (RPC)<br />

> Verstecken der Kommunikation hinter lokalen Prozeduren<br />

> Stubs (Stummel) sind lokale Proxies (Stellvertreter) des<br />

<strong>Aufrufe</strong>rs/Aufgerufenen, die meist (weitgehend) automatisch<br />

generiert werden<br />

....<br />

proc( a, 29 )<br />

....<br />

Stub<br />

Netz<br />

Stub<br />

proc( x, y )<br />

....<br />

....<br />

end-proc;<br />

Client<br />

Server<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 8


Client Stub<br />

> Lokaler Proxy für die aufzurufende Prozedur<br />

> Gleiche Prozedursignatur (Prozedurname, Parameter,<br />

Übergabearten) wie die aufzurufende Prozedur<br />

> Ruft ggf. Verzeichnis, Dienstvermittler auf, um Adresse des<br />

Servers zu ermitteln (Binding)<br />

> Packt Namen der aufzurufenden Prozedur und die Parameter in<br />

Anfragepaket (= Marshalling) und sendet es an den Server<br />

> Wartet auf und empfängt Antwortpaket vom Server Stub<br />

> Entpackt Ergebnisse aus dem Antwortpaket<br />

> Gibt Ergebnisse und Kontrolle an aufrufende Prozedur zurück<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 9


Client Stub – Exemplarisches Beispiel<br />

> Signatur der aufzurufenden Prozedur<br />

double square (double x1)<br />

> Stub (gleiche Signatur)<br />

double square (double x1) {<br />

request = new_request("square");<br />

add_double(request, x1);<br />

send_request(request, server);<br />

reply = receive_reply(request);<br />

return extract_double(reply);<br />

}<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 10


Server Stub<br />

> Lokaler Proxy für die aufrufende Prozedur<br />

> Wird vom Laufzeitsystem des Servers aufgerufen<br />

> Empfängt Anfragepaket und entpackt aus ihm Namen und<br />

Parameter der aufzurufenden Prozedur (= Unmarshalling)<br />

> Ruft die jeweilige Prozedur mit den Parametern auf<br />

> Packt Ergebnisse der Prozedur in Antwortpaket und<br />

sendet es an den Client Stub<br />

> Führt evtl. Verwaltungsarbeiten aus<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 11


Server Stub – Exemplarisches Beispiel<br />

> Wird von der <strong>Middleware</strong> aufgerufen, wenn eine<br />

entsprechende Nachricht empfangen wird<br />

message square_sstub (message request) {<br />

double x1 = extract_double(request);<br />

double x2 = square(x1);<br />

reply = new_reply(request);<br />

add_double(reply, x2);<br />

return reply;<br />

}<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 12


Interface Definition Language (IDL)<br />

> Ermöglicht deklarative, Programmiersprachen-unabhängige<br />

Schnittstellendefinitionen<br />

> Eine Schnittstelle (Interface) wird beschrieben durch<br />

> Namen der aufrufbaren Operationen<br />

> Namen und Typen der Parameter der einzelnen Operationen<br />

> Zusatzinformationen, z.B. eindeutige Kennzeichnung der Definition,<br />

Art einer Operation, Verhalten bei Fehlern, ...<br />

> [in], [out], [in, out] (* für Parameter *)<br />

> [maybe] (* Attribut für Operation *)<br />

> Server-Programmierer spezifiziert Schnittstelle mit IDL<br />

> Ein programmiersprachen-abhängiger Stub Compiler erzeugt<br />

daraus Stubs für Client und Server<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 13


RPC Eigenschaften<br />

> Getrennte Adressräume machen Adressen bedeutungslos<br />

> Nachbildung von call-by-reference durch call-by-copy/restore<br />

> Aufwendig für komplexe verkettete Strukturen<br />

> Synchroner (d.h. blockierender) Aufruf<br />

⇒ Parallele Anfragen an mehrere Server nur durch<br />

Multithreading<br />

> Die aufgerufene Prozedur kann weitere RPCs aufrufen<br />

⇒ Server werden (meist) multithreaded implementiert, um<br />

zeitweise Blockierung des Servers zu vermeiden<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 14


Threads<br />

> Leichtgewichtige Prozesse<br />

> Selbstständiger Kontrollfluss mit eigenem Stack<br />

> Mehrere Threads teilen sich einen Speicherbereich<br />

> Schnellere Kontextwechsel<br />

> Einfache Kommunikation durch gemeinsamen Speicher<br />

> Kein Schutz bei Zugriff auf gemeinsamen Speicher oder<br />

gleichzeitigem Aufruf einer Prozedur durch mehrere Threads<br />

⇒ Gefahr von Inkonsistenzen<br />

⇒ Synchronisation notwendig ⇒ Deadlock-Gefahr<br />

> Multithreading ermöglicht quasi-gleichzeitige <strong>Aufrufe</strong> und<br />

Bearbeitung von RPCs<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 15


Threads: Usage<br />

> Client several concurrent invocations<br />

> Server serving several clients concurrently<br />

Parallel<br />

Execution<br />

Server 1 Server 2<br />

Server 3<br />

A call is<br />

waiting<br />

One idle<br />

thread<br />

Client 1 Client 2 Client 3 Client 4<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 16


RPC Fehlersemantik<br />

> RPC hat andere Fehlersemantik<br />

als lokaler Prozeduraufruf!<br />

> Was kann alles schief gehen<br />

Client<br />

1. Client findet den Server nicht<br />

2. Client stürzt ab, nachdem er den Auftrag abgeschickt hat<br />

3. Auftrag geht verloren<br />

4. Server stürzt ab, nachdem er den Auftrag empfangen hat,<br />

aber bevor er die Antwort abgeschickt hat<br />

5. Antwort geht verloren<br />

6. Client stürzt ab, bevor er die Antwort erhalten<br />

(und bearbeitet) hat<br />

Server<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 17


RPC Fehlersemantik<br />

> Ist ein Fehler aufgetreten<br />

> Unterscheidung zwischen langsamen und verlorenen<br />

Nachrichten bzw. zwischen langsamen und abgestürztem<br />

Client bzw. Server in verteilten Systemen nicht möglich!<br />

> Client wartet auf Antwort zu seinem Auftrag<br />

> Wann soll er den Auftrag erneut schicken<br />

> Server wartet auf Bestätigung der Antwort/neuen Auftrag<br />

> Wann soll er die Antwort erneut schicken<br />

> Wie lange soll er die Antwort aufheben<br />

> Setzen von sinnvollen Timeouts äußerst schwierig!<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 18


RPC Fehlersemantik – Client Crash<br />

> Abgestürzte Clients blockieren Ressourcen beim Server<br />

(z.B. extra für den Client erzeugte Prozesse Waisen)<br />

> Mögliche Gegenmaßnahmen<br />

> Client schickt regelmäßig Heartbeat (Wie oft)<br />

> Server fragt nach, ob Client noch existiert (Wie oft)<br />

> Verbindungslose <strong>Aufrufe</strong><br />

> Neustart des Clients: alte Antworten dürfen nicht stören<br />

> Epochen-Zähler beim Neustart inkrementieren und im<br />

persistenten Speicher ablegen<br />

> Antworten aus vergangenen Epochen werden ignoriert<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 19


Steigende<br />

Komplexität<br />

RPC Fehlersemantik – Server Crash<br />

> Beim Client tritt Timeout beim Warten auf Antwort auf<br />

> Wie oft wurde der Auftrag ausgeführt<br />

> maybe evtl. gar nicht, einmal, mehrfach<br />

(einfach implementierbar)<br />

> at least once min. einmal (Wiederholungen)<br />

> at most once max. einmal (Seriennummern)<br />

> exactly once genau einmal<br />

Server<br />

Receive<br />

Execute<br />

Reply<br />

Server<br />

Receive<br />

Execute<br />

Crash<br />

Server<br />

Receive<br />

Crash<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 20


Kann „exactly once“-Semantik erreicht werden<br />

> Szenario: Client schickt Druckauftrag an Server<br />

> Server schickt eine Bestätigung, wenn der Auftrag eintrifft<br />

> Nach einem Crash schickt der Server „Wieder da“ an alle<br />

Clients<br />

> Erfährt der Client vom Crash des Servers, kann er den<br />

Auftrag wiederholen<br />

1. niemals<br />

2. immer<br />

3. nur, wenn Bestätigung eingetroffen ist<br />

4. nur, wenn Bestätigung nicht eingetroffen ist<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 21


Kann „exactly once“-Semantik erreicht werden<br />

> Aktionen des Servers<br />

> M schicke Bestätigung<br />

> P drucke Text<br />

> C Crash<br />

> Server kann Bestätigung schicken,<br />

> M P bevor der Druckauftrag angestoßen wird<br />

> P M nachdem der Druckauftrag angestoßen wurde<br />

> Betrachte den Fall eines Server-Crashs<br />

> Eine mögliche Reihenfolge ist: M P C<br />

> Sechs Reihenfolgen insgesamt<br />

(jeweils 3 für M P bzw. P M)<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 22


Kann „exactly once“-Semantik erreicht werden<br />

> Betrachte Kombinationen der Client- und Server-<br />

Strategien – wie oft wird der Druckauftrag ausgeführt<br />

⇒ Keine Strategie-Kombination, ist stets erfolgreich<br />

Client<br />

Server<br />

Strategie M P<br />

Strategie P M<br />

Wiederholung<br />

MPC<br />

MC(P)<br />

C(MP)<br />

PMC<br />

PC(M)<br />

C(PM)<br />

immer<br />

DUP<br />

OK<br />

OK<br />

DUP<br />

DUP<br />

OK<br />

niemals<br />

OK<br />

ZERO<br />

ZERO<br />

OK<br />

OK<br />

ZERO<br />

nur wenn bestätigt<br />

DUP<br />

OK<br />

ZERO<br />

DUP<br />

OK<br />

ZERO<br />

nur wenn nicht bestätigt<br />

OK<br />

ZERO<br />

OK<br />

OK<br />

DUP<br />

OK<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 23


Asynchronous RPC<br />

> Synchronous RPC most common<br />

> Sun RPC, DCE, J2EE, CORBA, .NET etc.<br />

> Asynchronous RPC<br />

⇒ Client is not blocked while waiting for reply<br />

> Two common approaches<br />

> Callback is executed when reply arrives<br />

(⇒ results are processed in a different context!)<br />

> Client polls local proxy for reply either non-blocking or<br />

blocking (with or without timeout)<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 24


Asynchronous RPC – Examples<br />

Request<br />

Request<br />

Request<br />

local<br />

polling<br />

processing<br />

of request<br />

Ack.<br />

blocking<br />

wait<br />

Reply<br />

Reply<br />

Reply<br />

callback<br />

invoked<br />

Client<br />

Server<br />

Client<br />

Server<br />

Client<br />

Server<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 25


Multicast RPC<br />

> Mehrere Instanzen der gleichen Prozedur<br />

(z.B. auf verschiedenen Rechnern) werden mit einem<br />

einzigen Aufruf aufgerufen<br />

> Für die Verarbeitung der Resultate gibt es mehrere<br />

Möglichkeiten<br />

> Die zuerst eintreffenden Resultate werden zurückgeliefert<br />

> Die eintreffenden Resultate werden zusammengefasst<br />

(z.B. per Mehrheitsentscheidung) und ein Resultat wird<br />

zurückgegeben<br />

> …<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 26


Remote Method Invocation (RMI)


Remote Method Invocation (RMI)<br />

> Übertragung des <strong>Konzepte</strong>s des entfernten<br />

Prozeduraufrufes auf objektorientierte<br />

Programmiersprachen <strong>Entfernte</strong>r Methodenaufruf<br />

> Objekt = Zustand + Verhalten (Methoden)<br />

> Zustand alleine nützt (meist) nichts<br />

⇒ Übertragung von Objekten by value oder by copy/restore<br />

ist in heterogenen Systemen problematisch<br />

> Der Aufgerufene muss Zugriff auf die Implementierung der<br />

Methoden haben und diese auch ausführen können<br />

⇒ Häufig können Objekte daher nur per reference<br />

übergeben werden <strong>Entfernte</strong> Objektreferenz<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 28


<strong>Entfernte</strong> Objektreferenz<br />

> Identifiziert ein Objekt eindeutig in einem verteilten<br />

System<br />

> Exemplarischer Aufbau<br />

> IP-Adresse des Servers + TCP-Portnummer<br />

> Objektkennung<br />

192.168.0.1:4444:123456<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 29


Distributed Object <strong>Middleware</strong><br />

> <strong>Middleware</strong>-Plattformen basierend auf dem Konzepts des<br />

entfernten Methodenaufrufes<br />

> Beispiele<br />

> Common Object Request Broker Architecture (CORBA)<br />

> Java 2 Enterprise Edition (J2EE)<br />

> .NET<br />

> …<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 30


Common Object Request Broker Architecture<br />

(CORBA)


Object Request Broker (ORB)<br />

> "Software Bus" für verteilte Objektsysteme<br />

> Wie ein Hardware-Bus verschiedene Hardware-<br />

Komponenten verbindet, so verbindet der ORB<br />

verschiedene Software-Komponenten<br />

Object<br />

Request<br />

Broker<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 32


Objektmodell<br />

Client<br />

> Instanz einer Klasse<br />

> Hat einen Zustand<br />

> Besitzt "Namen" und Lebenszeit<br />

> Objekt<br />

> Klasse<br />

> Schablone für Objekte<br />

> Verfeinerung durch Vererbung<br />

> Polymorphe Substitution<br />

> Schnittstelle (Interface) eines Objektes<br />

> Methoden und Attribute<br />

> Kapselung der Implementierung<br />

Schnittstelle<br />

Server<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 33


Object Request Broker (ORB)<br />

> Einbettung von Objekt-Implementierungen<br />

("Server-Objekte")<br />

> Vergabe von Objektreferenzen<br />

> Entgegennehmen von <strong>Aufrufe</strong>n des Clients<br />

> Transport der <strong>Aufrufe</strong> zum Server<br />

> Ggf. Aktivierung eines Server-Objektes<br />

> Übergabe des Aufrufs an das Server-Objekt<br />

> Entgegennehmen von Ergebnissen und Transport /<br />

Rückgabe an den Client<br />

> Unterstützung von Sicherheits- und<br />

Abrechnungsfunktionen<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 34


CORBA-Schnittstellen<br />

Client<br />

Objekt-Implementierung<br />

Dynam.<br />

Aufruf<br />

IDL<br />

Stub<br />

ORB<br />

Interface<br />

Dynam.<br />

Skeleton<br />

IDL<br />

Skeleton<br />

Objekt-<br />

Adapter<br />

Interface Repository<br />

ORB-Kern<br />

Implementation Rep.<br />

standardisiert<br />

intern<br />

Anwendung<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 35


CORBA IDL<br />

Schnittstelle<br />

Client<br />

C<br />

C++<br />

Smalltalk<br />

Cobol<br />

Ada<br />

Java<br />

.....<br />

IDL<br />

Server<br />

interface Quoter {<br />

double get_quote (in string stock_name);<br />

};<br />

<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 36


Entwicklung einer Anwendung<br />

interface Quoter {<br />

.....<br />

};<br />

IDL<br />

IDL Compiler<br />

Client Stub<br />

Server Skeleton<br />

Client<br />

Server<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 37


Ablauf<br />

1. Definition der Schnittstellen in IDL<br />

2. Mittels IDL-Compiler Stubs und Skeletons generieren<br />

3. Implementierung des Klienten<br />

4. Implementierung des Servants<br />

(d.h., der Objektimplementierung)<br />

5. Implementierung des Servers<br />

6. Registrierung des Servants beim ORB<br />

7. Methodenaufrufe des Klienten auf dem Objekt<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 38


Statische <strong>Aufrufe</strong><br />

> Verwenden das Static Invocation Interface (SII)<br />

> Schnittstellen stehen zur Compile-Zeit fest<br />

> IDL-Compiler erzeugt aus den Schnittstellen die Stubs<br />

> Typüberprüfung schon zur Compile-Zeit möglich<br />

> Stub vertritt die lokal nicht vorhandenen Prozedur<br />

> Kaum Unterschiede zum lokalen Aufruf<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 39


Dynamische <strong>Aufrufe</strong><br />

> Verwenden das Dynamic Invocation Interface (DII)<br />

> DII ist unabhängig von der konkreten Schnittstelle des<br />

aufgerufenen Objekts<br />

> Vorteil: Schnittstelle muss nicht zur Compile-Zeit<br />

vorliegen, da Aufruf zur Laufzeit zusammengestellt wird<br />

> Allerdings deutlich mehr Code notwendig<br />

> Normalerweise deutlich ineffizienter, als statische <strong>Aufrufe</strong><br />

> Typüberprüfung erst zur Laufzeit möglich<br />

> Folgende Angaben sind für einen Aufruf notwendig<br />

> Objekt, Operation, Argumente (Anzahl, Typ, Modus, Wert),<br />

Rückgabetyp<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 40


Ablauf eines dynamischen Aufrufs<br />

1. Objektreferenz beschaffen (z.B. über Name Service)<br />

2. Schnittstelle bestimmen (z.B. im Interface Repository)<br />

3. Request Pseudo Object erzeugen und füllen<br />

( = Behälter für die zum Aufruf gehörenden Informationen)<br />

4. Request Pseudo Object an ORB übergeben<br />

( = Starten des Aufrufs)<br />

5. Auf Ergebnis warten (optional)<br />

6. Request Pseudo Object löschen oder wieder verwenden<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 41


Mögliche Aufrufarten mit dem SII und dem DII<br />

> Synchroner Aufruf<br />

> Client blockiert bis Antwort zurück (oder Fehler)<br />

> Aufruf- und Rückgabeparameter möglich<br />

> Möglich für statische und dynamische <strong>Aufrufe</strong><br />

> Oneway Aufruf ( = "fire and forget“ )<br />

oneway void sayGoodBye(...);<br />

> Kein Rückgabewert oder Rückgabeparameter<br />

> Keine Exceptions bei Fehlern<br />

> Semantik hängt vom ORB ab<br />

(können z.B. auch blockierend sein!)<br />

> Möglich für statische und dynamische <strong>Aufrufe</strong><br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 42


Mögliche Aufrufarten mit dem SII und dem DII<br />

> Asynchroner Aufruf (Deferred Synchronous)<br />

> Client blockiert nicht<br />

> Aufruf- und Rückgabeparameter möglich<br />

> Zustand des Request-Objekts kann abgefragt werden<br />

> Nur möglich für dynamische <strong>Aufrufe</strong><br />

> Bedarf für asynchrone <strong>Aufrufe</strong> mittels des SIIs AMI<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 43


Mögliche Aufrufarten mit dem AMI<br />

> CORBA Messaging (ab CORBA 2.3) ermöglicht asynchrone<br />

<strong>Aufrufe</strong> mit dem SII Asynchronous Method Invocation (AMI)<br />

> AMI unterstützt zwei Modelle<br />

> Callback Model<br />

> Client gibt dem Aufruf eine Objektreferenz für Antwort mit<br />

> ORB benutzt diese Objektreferenz, um Antwort abzuliefern<br />

> Client muss als Server agieren<br />

> Ergebnis wird nicht im Kontext des <strong>Aufrufe</strong>nden verarbeitet<br />

> Polling Model<br />

> Aufruf gibt sofort ein Pseudo-Objekt zurück<br />

> Client kann an diesem Objekt pollen bzw. warten<br />

> Ergebnis wird im Kontext des <strong>Aufrufe</strong>nden verarbeitet<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 44


Zusammenfassung der möglichen Aufrufarten<br />

Static Invocation<br />

Interface (SII)<br />

Dynamic Invocation<br />

Interface (DII)<br />

Asynchronous<br />

Invocation<br />

Interface (AMI)<br />

Two-Way<br />

Synchronous Call<br />

Oneway<br />

Call<br />

Deferred<br />

Synchronous Call<br />

Asynchronous<br />

Call (Callback)<br />

Asynchronous<br />

Call (Polling)<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 45


CORBA Beispiel: Stock Quote Server<br />

> Szenario: Aktienkurse sollen von einem Server an eine Menge<br />

von Clients zugestellt werden<br />

> Mehrere Implementierungen sind möglich<br />

> Pull: Der Server bietet über eine Schnittstelle die aktuellen Kurse<br />

diverser Aktien an; Clients fragen diese (periodisch) ab<br />

> Synchrone <strong>Aufrufe</strong> (SII oder DII möglich)<br />

> Asynchrone <strong>Aufrufe</strong> mit dem DII<br />

> Asynchrone <strong>Aufrufe</strong> mit AMI (Callback oder Polling Model)<br />

> Push: Clients registrieren Callbacks beim Server; dieser ruft beim<br />

Vorliegen eines neuen Kurses den Callback beim Client auf<br />

> Synchrone Aufruf (SII oder DII möglich)<br />

> Oneway-<strong>Aufrufe</strong><br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 46


1. Implementierungsmöglichkeit: Pull


CORBA Example: Stock Quote Server<br />

module Stock<br />

// CORBA IDL implemented by server developer<br />

{<br />

// Requested stock does not exist.<br />

exception Invalid_Stock {};<br />

interface Quoter {<br />

// Two-way operation to retrieve current stock value.<br />

double get_quote (in string stock_name)<br />

raises (Invalid_Stock);<br />

};<br />

}<br />

// ...<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 48


Used Classes<br />

Quoter<br />

double get_quote (<br />

in string stock_name)<br />

…<br />

IDL written by server developer<br />

Stubs generated by IDL compiler<br />

Servant implemented by server developer<br />

Stock::QuoterBOAImpl<br />

double get_quote (<br />

const char *stock_name)<br />

Quoter_var<br />

double get_quote (<br />

const char *stock_name)<br />

…<br />

Client-Side<br />

RMI<br />

MyQuoter<br />

double get_quote (<br />

const char *stock_name)<br />

Server-Side<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 49


Example: Stock Quote Server<br />

(Servant)<br />

// C++ implementation class for IDL interface.<br />

class My_Quoter<br />

// Inherits from a generated CORBA skeleton class.<br />

: virtual public Stock::QuoterBOAImpl<br />

{<br />

public:<br />

My_Quoter (Quote_Database *db): db_ (db) {}<br />

// Invoked by the CORBA skeleton.<br />

virtual double get_quote (const char *stock_name)<br />

throw (Stock::Invalid_Stock) {<br />

double value =<br />

db_->lookup_stock_price (stock_name);<br />

if (value == -1) throw Stock::Invalid_Stock();<br />

return value;<br />

}<br />

private:<br />

Quote_Database *db_;<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 50


Example: Stock Quote Server<br />

(Server Side)<br />

// Pointer to online stock quote database.<br />

extern Quote_Database *quote_db;<br />

int main (int argc, char *argv[])<br />

{<br />

// Initialize the ORB and the BOA.<br />

CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, 0);<br />

CORBA::BOA_var boa = orb->boa_init (argc, argv, 0);<br />

// Create an object implementation.<br />

My_Quoter quoter (quote_db);<br />

}<br />

// Single-threaded event loop that handles CORBA<br />

// requests by making callbacks to the user-supplied<br />

// object implementation of My_Quoter.<br />

boa->impl_is_ready ();<br />

/* NOTREACHED */<br />

return 0;<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 51


Example: Stock Quote Server<br />

(Client Side)<br />

int main (int argc, char *argv[])<br />

{<br />

CORBA::Object_var obj =<br />

orb -> string_to_object(argv[1]);<br />

Quoter_var q = Quoter::_narrow (obj);<br />

}<br />

const char *stock_name = "ACME ORB Inc.";<br />

try {<br />

double value = q -> get_quote (stock_name);<br />

return 0;<br />

} catch (Invalid_Stock &) {<br />

return 1;<br />

}<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 52


Deferred Synchronous Invocations mit dem DII<br />

void get_stock_quotes(Stock::Quoter_ptr quoter_ref)<br />

{<br />

CORBA::Request_var *requests[NUM_STOCKS];<br />

for (i = 0; i < NUM_STOCKS; i++) {<br />

requests[i] = quoter_ref -> _request ("get_quote");<br />

requests[i] -> add_in_arg () send_deferred ();<br />

}<br />

}<br />

for (i = 0; i < NUM_STOCKS; i++) {<br />

requests[i] -> get_response();<br />

quotes[i] = request->return_value ();<br />

}<br />

> Concurrent calls can be issued since calls are non-blocking<br />

> Here, the overall execution time is dominated by the longest call<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 53


Asynchronous Method Invocation<br />

> IDL compiler generates additional stubs for asynchronous<br />

calls implied IDL<br />

> One version for the polling and one for the callback model<br />

> Clients must be rewritten to use asynchronous calls<br />

> Servers does not need to be changed<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 54


Used Classes (AMI Polling Model)<br />

Quoter<br />

double get_quote (<br />

in string stock_name)<br />

AMIQuoterPoller<br />

void get_quote (<br />

long timeout,<br />

double ami_return_val)<br />

Quoter_var<br />

double get_quote (<br />

const char *stock_name)<br />

AMI_QuoterPoller* sendp_get_quote (<br />

const char *stockname)<br />

…<br />

IDL written by server developer<br />

Stub generated by IDL compiler<br />

Poller object generated by IDL compiler<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 55


CORBA: AMI Polling Model (Client)<br />

void get_stock_quotes(Stock::Quoter_ptr quoter_ref) {<br />

// C++ implemented by client developer<br />

Stock::AMI_QuoterPoller *pollers[NUM_STOCKS];<br />

// issue calls to get stock quotes from exchange<br />

for (i = 0; i < NUM_STOCKS; i++)<br />

pollers[i] =<br />

quoter_ref -> sendp_get_quote(stock_symbols[i]);<br />

// collect replies<br />

for (i = 0; i < NUM_STOCKS; i++)<br />

pollers[i] -> get_quote(MAX_TIMEOUT, quotes[i]);<br />

}<br />

> Relies on the tedious Objects-by-Value (OBV) specification<br />

> The execution time is dominated by largest request duration<br />

> Reply handled in the context of the caller<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 56


CORBA: AMI Polling Model (Poller Objects)<br />

> AMI_QuoterPoller is a valuetype generated by the IDL<br />

compiler object instances are always collocated and,<br />

therefore, calls to them are local<br />

namespace Stock {<br />

// C++ generated by IDL compiler<br />

class AMI_QuoterPoller : public Messaging::Poller {<br />

public:<br />

virtual void get_quote (<br />

long timeout,<br />

double ami_return_val);<br />

};<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 57


CORBA: AMI Polling Model (sendp_ methods)<br />

> sendp_ methods are also generated by the IDL compiler<br />

namespace Stock {<br />

// C++ generated by IDL Compiler<br />

class Quoter : public virtual CORBA::Object<br />

{<br />

public:<br />

Stock::AMI_QuoterPoller*<br />

sendp_get_quote (const char *stockname);<br />

// ...<br />

};<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 58


Used Classes (AMI Callback Model)<br />

Quoter<br />

double get_quote (<br />

in string stock_name)<br />

AMI_QuoterHandler<br />

void get_quote (<br />

double d)<br />

StockHandler<br />

void get_quote (<br />

double d)<br />

Quoter_var<br />

double get_quote (<br />

const char *stock_name)<br />

void sendc_get_quote(<br />

AMI_QuoterHandler_ptr,<br />

const char *stockname);<br />

…<br />

IDL written by server developer<br />

Stubs generated by IDL compiler<br />

Callback to be implemented by client developer<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 59


CORBA: AMI Callback Model (Client)<br />

void get_stock_quotes(Stock::Quoter_ptr quoter_ref) {<br />

// C++ implemented by client developer<br />

// Initialize handler servants<br />

for (i = 0; i < NUM_STOCKS; i++)<br />

handlers[i] = new Stock_Handler(i);<br />

// Initialize handler object references<br />

for (i = 0; i < NUM_STOCKS; i++)<br />

handler_ref[i] = handlers[i]->_this ();<br />

}<br />

// Issue asynchronous calls using the callback model<br />

for (i = 0; i < NUM_STOCKS; i++)<br />

quoter_ref -> sendc_get_quote<br />

(handler_ref[i], stock_symbols[i]);<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 60


CORBA: AMI Callback Model (send_c methods)<br />

namespace Stock<br />

{<br />

// C++ generated by IDL Compiler<br />

class Quoter : public virtual CORBA::Object<br />

{<br />

public:<br />

void sendc_get_quote(Stock::AMI_QuoterHandler_ptr,<br />

const char *stockname);<br />

// ...<br />

};<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 61


CORBA: AMI Callback Model (Handler Objects)<br />

namespace POA_Stock<br />

{<br />

// C++ generated by IDL Compiler<br />

class AMI_QuoterHandler<br />

: public POA_Messaging::ReplyHandler<br />

{<br />

public:<br />

virtual void get_quote (CORBA::Double d) = 0;<br />

virtual void get_quote_excep<br />

(Stock::AMI_QuoterExceptionHolder *excep)= 0;<br />

};<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 62


CORBA: AMI Callback Model (Client Servant)<br />

class Stock_Handler<br />

: public POA_Stock::AMI_QuoteHandler<br />

{ // C++ implemented by client developer<br />

public:<br />

Stock_Handler(const int i){ i_=i; }<br />

virtual void get_quote(CORBA::Double value)<br />

throw (CORBA::SystemException)<br />

{ quotes[i_] = value; }<br />

virtual void get_quote_excep<br />

(Stock::AMI_QuoterExceptionHolder *excep)<br />

throw (CORBA::SystemException, Stock::Invalid_Stock)<br />

{ ... }<br />

}<br />

private int i_;<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 63


2. Implementierungsmöglichkeit: Push


Callbacks using oneway Methods<br />

> Clients call the register_callback method to register a callback at<br />

the server<br />

> Server calls callback to deliver new quote<br />

> Requires clients to behave as a “server”<br />

> Using synchronous calls for callbacks would raise the problem<br />

that the server could be blocked by a “slow” client<br />

> oneway IDL keyword in interface<br />

> Indicates that no reply should be passed back to the caller<br />

> Best effort and (not guaranteed to be) non-blocking<br />

> Application must handle end-to-end reliability<br />

> Semantic depends on ORB implementation<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 65


Callbacks using One-Way Methods<br />

module Stock { // CORBA IDL<br />

...<br />

module Callback<br />

{<br />

struct Info<br />

{<br />

string stock_name; double value;<br />

};<br />

interface Handler<br />

{<br />

// Oneway method called by quote server to<br />

// deliver new quote<br />

oneway void push(in Info data);<br />

};<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 66


Callbacks using One-Way Methods<br />

};<br />

};<br />

interface Notifying_Quoter<br />

{<br />

// Called by clients to register a callback<br />

void register_callback(in string stock_name,<br />

in Callback::Handler handler)<br />

raises (Invalid_Stock);<br />

// Called by clients to unregister a callback<br />

void unregister_callback(in string stock_name,<br />

in Callback::Handler handler)<br />

raises (Invalid_Stock);<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 67


Client‘s Callback Implementation<br />

class My_CallBack<br />

: public POA_Stock::Callback::Handler<br />

{<br />

public:<br />

// Handle callback from quoter supplier.<br />

void push (const Stock::Callback::Info& info)<br />

{<br />

double price = info.value;<br />

string stock_name = info.stock_name;<br />

...<br />

}<br />

};<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 68


Client Implementation<br />

int main (int argc, char** argv)<br />

{<br />

// Initialize the ORB and the BOA.<br />

CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, 0);<br />

CORBA::BOA_var boa = orb->boa_init (argc, argv, 0);<br />

// Create a new implementation object.<br />

My_Callback* cb = new My_Callback;<br />

// Get the callback object reference.<br />

Callback::Handler_var handler = cb->_this ();<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 69


Client Implementation<br />

// Obtain a Notifying_Quoter object reference,<br />

// e.g., from the Naming or Trader service<br />

Notifying_Quoter_var quoter = // ...<br />

// Register callback with the supplier.<br />

quoter -> register_callback<br />

("ACME ORB Inc.", handler);<br />

}<br />

// Now instruct the object adapter to<br />

// wait for callbacks from the supplier.<br />

boa->impl_is_ready ();<br />

/* NOTREACHED */<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 70


Bibliography<br />

1. Object Management Group (OMG). CORBA Messaging Specification. OMG Document<br />

orbos/98-0505, May 1998.<br />

2. D. C. Schmidt and S. Vinoski. Comparing Alternative Client Distributed Programming<br />

Techniques. C++ Report, 7(4), May 1995.<br />

http://www.cs.wustl.edu/~schmidt/PDF/C++-report-col3.pdf<br />

3. D. C. Schmidt and S. Vinoski. Distributed Callbacks and Decoupled Communication in CORBA.<br />

C++ Report, 8(9), Oct. 1996.<br />

http://www.cs.wustl.edu/~schmidt/PDF/C++-report-col8.pdf<br />

4. D. Schmidt and S. Vinoski. An Introduction to CORBA Messaging. C++ Report, 10(10), Nov.<br />

1998.<br />

http://www.cs.wustl.edu/~schmidt/PDF/C++-report-col15.pdf<br />

5. D. C. Schmidt and S. Vinoski. Programming Asynchronous Method Invocations with CORBA<br />

Messaging. C++ Report, 11(2), Feb. 1999.<br />

http://www.cs.wustl.edu/~schmidt/PDF/C++-report-col16.pdf<br />

6. D. Schmidt and S. Vinoski. Time-Independent Invocation and Interoperable Routing. C++<br />

Report, 11(4), Apr. 1999.<br />

http://www.cs.wustl.edu/~schmidt/PDF/C++-report-col17.pdf<br />

7. Microsoft Corp. .NET Framework Developer's Guide: Asynchronous Programming Overview.<br />

http://msdn.microsoft.com/library/default.aspurl=/library/enus/cpguide/html/cpovrasynchronousprogrammingoverview.asp<br />

<strong>Middleware</strong>-<strong>Konzepte</strong> © Gero Mühl 71

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!