Clemens Düpmeier, 09.03.22
Verteilte Kommunikation oberhalb der Socket-API
Datencodierung,
Remote Procedure Calls,
Verteilte Objektkommunikation,
Namensdienste und Ortstranparenz
Clemens Düpmeier, 09.03.22
Zunächst mal 2 Probleme
• Kommunikation basiert auf Nachrichtenaustausch (über Sockets)
• Ein grundsätzliches Problem mit Sockets ist
– Wir müssen Encoding / Decoding der Nachrichten definieren, dass jeder Kommunikationspartner versteht
– Nachrichten sollen dabei beliebig komplex sein können (i.e. auch komplexe binäre Strukturen)
• 2. Problem:
– Wir brauchen einfache, aber universell funktionierende Mechanismen an Stelle von selbst-definierten Protokollen (Abstraktion oberhalb der Protokollebene)
• Höherwertige Kommunikationsmechanismen stellen Lösungen für diese beiden Probleme bereit
Endianness einer Binärcodierung
• Ganzzahl 16.909.060 als 32-Bit-Integer-Wert
gespeichert
(hexadezimal: 01020304
h)
• Die Speicherung erfolgt in 4 Bytes ab
Speicheradresse 10000
Clemens Düpmeier, 09.03.22
Clemens Düpmeier, 09.03.22
Übertragung komplexer binärer Daten
Clemens Düpmeier, 09.03.22
Externe Datenrepräsentation
• Höherwertige Kommunikationsmechanismen nutzen ein
gemeinsames Datenformat, genannt externe Datendarstellung zur transparenten Übertragung von beliebigen (binären) Daten.
• Notwendig wegen der Heterogenität der Umgebungen
– Unterschiedliche Hardwarearchitektur – Verschiedene Betriebssysteme
– Verschiedene Programmiersprachen
• Unter Marshalling versteht man den Prozess der Transformation
strukturierter Datenelemente und elementarer Werte in eine (mit einer Nachricht übertragbaren) externe Datendarstellung
• Unter Un-Marshalling versteht man den Prozess der Erstellung elementarer Werte aus ihrer externen Datendarstellung und den Wiederaufbau der ursprünglichen Datenstrukturen.
Clemens Düpmeier, 09.03.22
Formen von externen Darstellungen
Sender und Empfänger sind sich über die Reihenfolge und die Typen der Datenelemente in einer Nachricht einig
• ISO: ASN.1 (Abstract Syntax Notation)
• Sun ONC (Open Network Computing)-RPC: XDR
(eXternal Data Representation)
• Corba: IDL und CDR (Common Data Representation): CDR bildet IDL-Datentypen in Bytefolgen ab.
Vollständige Informationen über Reihenfolge und die Typen der Datenelemente sind in einer Nachricht enthalten
• Java: Objektserialisierung, d.h.
Abflachung eines (oder
mehrerer) Objektes zu einem seriellen Format inkl.
Informationen über die Klassen.
Deserialisierung ist die Wiederherstellung eines
Objektes ohne Vorwissen über die Typen der Objekte.
0–3 4–7 8–11 12–15 16–19 20-23 24–27
5
"Smit"
"h___"
6
"Lond"
"on__"
1934 Index in Bytefolge 4 Byte
Länge der Zeichenkette
“Smith”
Länge der Zeichenkette
“London”
unsigned int Struct Person{
string name;
string place;
unsigned int year;
};
Typ Sequence
String Array Struct Enumerated
Darstellung
Länge gefolgt von Elementen in der angegebenen Reihenfolge Länge gefolgt von Zeichen in der angegebenen Reihenfolge Array-Elemente in der angegebenen Reihenfolge
Die Reihenfolge der Deklarationen der Komponenten Unsigned Long
Reihenfolge und Typen der Elemente bei Sender und Empfänger bekannt!
Smith London 1934
Person 3
1934
8-Byte Versionsnummer int year
5 Smith
java.lang.String name:
6 London
h0
java.lang.String place:
h1
Klassenname, Versionsnummer
Nummer, Typ und Name der Instanzvariablen
Werte der Instanzvariablen Das echte serialisierte Format enthält zusätzliche Typkennzeichner;
h0 und h1 sind Handles, also Verweise auf serialisierte Objekte
public class Person implements Serializable{
private String name;
private String place;
private int year;
public Person(String aName, String aPlace, int aYear) { name = aName;
place = aPlace;
year = aYear; }
// gefolgt von Methoden für den Zugriff auf die Instanzvariablen }
Person p = new Person(„Smith“,“London“,1934);
Clemens Düpmeier, 09.03.22
Fazit
• Zuerst die schlechte Nachricht: das sieht alles ziemlich kompliziert zu implementieren aus,
und das ist es auch!
• Die gute Nachricht: Solche externen
Datendarstellungen sind schon konzipiert und implementiert
– und ihre Nutzung ist (insbesondere bei
objektorientierten Sprachen) einfach
Bsp.: Protocol Buffers, ASN.1
Selbst ansehen
• https://www.oss.com/asn1/resources/asn1-mad e-simple/introduction.html
(Kleine Einführung ASN.1)
• https://developers.google.com/protocol-buffe (Protocol Buffers) rs
Clemens Düpmeier, 09.03.22
Clemens Düpmeier, 09.03.22
Elementare Kommunikationsmuster
Clemens Düpmeier, 09.03.22
Blockierende, synchrone Interaktion
• über Anfrage-Anwort (Request-Reply) Protokoll – Client schickt Anfrage-Nachricht an Server – Server empfängt Nachricht und führt
zugehörige Aktion durch
– Server sendet Antwort-Nachricht an Client zurück
• Ausführung auf dem Client blockiert nach Schicken der Anfrage-Nachricht so lange, bis Antwort-Nachricht erhalten wurde
• Beide, Client und Server, müssen zur Zeit der Interaktion verfügbar sein
– Wenn nicht, muss durch wiederholtes Senden von Nachrichten Fehlersituation bereinigt
werden
• Typischer Weise über Verbindungs-orientierte Sockets implementiert
• Punkt-zu-Punkt Verbindung – Kommunikationspartner
müssen direkt verbunden sein (Keine Message-Router dazwischen)
• Viele mögliche Fehlersituationen
Clemens Düpmeier, 09.03.22
Mögliche Fehlersituationen bei Request-Reply
Client Server
1) Verlust der Auftragsnachricht 2) Verlust der Ergebnisnachricht 3) Ausfall des Servers
4) Ausfall des Clients
1)
2)
4) 3)
Clemens Düpmeier, 09.03.22
Client Server
TimeoutTimeoutTimeout
Request
Reply
Request Bearbeitung des Requests
Reply
Request Bearbeitung des Requests Ergebnis kann
verschieden sein!
Ergebnis kann verschieden sein!
at least once Semantik at least once Semantik
Client Server
TimeoutTimeoutTimeout
Request
at most once Semantik at most once Semantik
Liste der Requests Liste der Requests
Reply
Request Bearbeitung des Requests;
Request eintragen
Bearbeitung des Requests;
Request eintragen
Reply
Request Liste der Requests über- prüfen; Verwerfen des 2.
Requests
Liste der Requests über- prüfen; Verwerfen des 2.
Requests Acknowledge-
ment Request löschenRequest löschen
Clemens Düpmeier, 09.03.22
Fehlersemantiken und Eigenschaften
Clemens Düpmeier, 09.03.22
Weiteres zur Fehlerbehandlung
• Um zu verhindern, dass ein Service vorübergehend nicht verfügbar ist, kann
– Replizierung des Service (Serverteils) und
automatische Lastverteilung und Relokation bei Fehlern eingesetzt werden
• Für eine "Exactly Once"-Strategie und
kompliziertere Konsistenzerhaltung von Daten
benötigt man Transaktionskonzept (siehe später)
Clemens Düpmeier, 09.03.22
Remote Procedure Calls (RPC)
Vorläufer der Verteilten
Objektkommunikationsmechanismen
Clemens Düpmeier, 09.03.22
Idee für einen entfernten Prozeduraufruf
Clemens Düpmeier, 09.03.22
Remote Procedure Calls (Sun-RPC)
• Realisieren entfernten Funktionsaufruf
– übernehmen Funktion des Anwenderprotokolls bei Socket- orientierter Kommunikation
– At least once Semantik (d.h. entfernter Prozeduraufruf wird mindestens 1-mal ausgeführt)
– synchrone Kommunikation
– beliebig komplexe Argument(e) und Returnwerte werden als
komplexe Datenstrukturen aufgefasst und mit XDR kodiert
übertragen bzw. dekodiert.
Clemens Düpmeier, 09.03.22
Synchrone Kommunikation in RPC‘s
Zeit Server
Client Client vor Aufruf RPC Aufruf
Lokale Prozedur
RPC Return
Client wartet Client nach Aufruf
Lokale Funktion
aufrufen
Clemens Düpmeier, 09.03.22
Registrierung von RPC Programmen
Client System Server System
Client Programm
Portmap / rpcbind
111
RPC Server
Registrierung Lookup
RPC Call
Clemens Düpmeier, 09.03.22
Beispiel für RPC Server (Low Level)
• Registrierung einer lokalen Prozedur im Laufzeitsystem des Servers unter Angabe von
– Programmnummer, Version
– Prozedurnummer – Lokaler Funktion
– Parameterdecodierung – Returnwertdecodierung
• Starten der
Laufzeitinfrastruktur des Servers
– Laufzeitinfrastruktur registriert Programme und Prozeduren im Namensdienst
#include <stdio.h>
#include <rpc/rpc.h>
#include <rpcsvc/rusers.h>
/* lokale Funktion, die Anzahl Benutzer feststellt */
void *rusers();
main() {
if (rpc_reg(RUSERSPROG,RUSERSVERS,RUSERSPROCNUM,rusers, xdr_void, xdr_u_int, /* Welche Argument hat RPC Prozedur, * was wird zurückgegeben */
"visible") == -1) /* Tranportwege = hier alle */
{
fprintf(stderr, "Couldn't register myself as RPC program\n");
exit(1);
}
svc_run(); /* Endlosschleife,
* nur return, wenn durch Signal abgebrochen */
fprintf(stderr, "Programm wurde beendet\n");
exit(1);
}
Clemens Düpmeier, 09.03.22
Beispiel für RPC Client (Low Level)
• Aufruf der Prozedur unter Angabe von
– Hostname, – Programmnr.,
Version
– Prozedurnummer – Codierer +
Parameter – Decodierer,
Variable für Returnwert
• Ausgabe des Wertes auf Standardausgabe
/* einige includes */
main(argc, argv) int argc;
char **argv;
{
unsigned int nusers; enum clnt_stat cs;
if (argc != 2) {
fprintf(stderr,"usage: rusers hostname\n");
exit(1);
}
if (cs= rpc_call(argv[1], RUSERSPROG, /* Programmnummer */
RUSERSVERS, RUSERSPROC_NUM,/* Version, Prozedur */
xdr_void, (char *)0, /* Argumente */
xdr_u_int, (char *)&nusers, /* Returnwert */
"visible") != RPC_SUCCESS) {
clnt_perrno(cs); /* Gebe RPC Fehlercode auf Console aus */
exit(1);
}
fprintf(stdout, "%d users on %s\n", nusers, argv[1]);
exit(1);
}
Clemens Düpmeier, 09.03.22
Low Level RPC sieht wirklich hässlich aus
• Problem: sieht noch nicht wirklich wie lokaler Prozeduraufruf aus
• Lösung hierfür ist Stub- und Skeleton Generierung
– Führe RPC Sprache ein, mit der RPC Aufrufe bzgl. Parameter (welche XDR Typen gehören dazu, etc.) spezifiziert werden – RPC-Compiler generiert daraus lokale Funktionen
• XDR-Kodierungs- und Dekodierungsfunktionen
• Stubs für die Clientseite (sehen wie lokale Funktionen aus)
• Anwendungsprogrammierer benutzt nur die Stubs
• Skeleton für die Serverseite (Skeleton ruft normale Anwenderprozedur auf)
• Anwendungsprogrammierer programmiert nur Anwendungsprozeduren
• Stubs und Skeleton kommunizieren dann miteinander über die bereits vorgestellte Low Level RPC Schnittstelle
• Ähnliches Prinzip sehen wir gleich auch bei RMI und CORBA
Clemens Düpmeier, 09.03.22
main(argc, argv) int argc;
char **argv;
{
unsigned int nusers;
if (argc != 2) {
fprintf(stderr,"usage: rusers hostname\n");
exit(1);
}
nusers=rusers(argv[1]); // Aufruf Stub
fprintf(stdout, "%d users on %s\n", nusers, argv[1]);
exit(1);
}
int rusers(char *hostnname) {
if (cs= rpc_call(hostname, RUSERSPROG, /* Programmnummer */
RUSERSVERS, RUSERSPROC_NUM,/* Version, Prozedur */
xdr_void, (char *)0, /* Argumente */
xdr_u_int, (char *)&nusers, /* Returnwert */
"visible") != RPC_SUCCESS) return -1;
else return cs;
}
Stub-
oder Proxy Aufruf von Stub
Bedeutung von
Stubs
Clemens Düpmeier, 09.03.22
Wo wird RPC eingesetzt?
• RPC Einsatz findet sich an vielen Stellen bei Linux und Windows Betriebssystemen
• Beispiele Unix / Linux
– NFS - Network File Sytem
– YP - YP / NIS Verzeichnisdienst
– Mount Daemon für das Mounten von Netzwerklaufwerken – ...
• Windows - alles an Diensten, was abhängig vom RPC Dienst ist – COM+ Ereignissystem (COM+ Kommunikation allgemein) – Dateireplikation
– Distributed Transaction Dienst – Druckerdienst
– ...
RPC Schnittstellen stellen oftmals unbekannte Sicherheitslücken im Netz dar
Gibt es alternative Lösungen?
• Bessere RPC-basierte Alternativen für die moderne Internet-Technologie getriebene IT-Welt
– Z.B. JSON-RPC
– oder gRPC basierend auf Protocol Buffer
• Verteilte Objektkommunikation
• Web-Services
– SOAP-basierte Web-Services – REST-basierte Web-Services
Clemens Düpmeier, 09.03.22
gRPC Entwicklungs-Workflow
09.03.22
gRPC – RPC on Steroids
09.03.22
Sprachübergreifende RPC Technologie, welche Protobuf Datencodierung nutzt
Clemens Düpmeier, 09.03.22
Einige Eigenschaften von gRPC
• Allows classic RPC (Remote Function Call – Request-Response Pattern)
• But also streaming RPC patterns
• Multi-language: Java, Go, C, C++, Node.js, Python, Ruby, Objective- C, PHP and C#
• IDL and Data Encoding: Protocol Buffers 3, Flatbuffers
• Transport-Protokoll: HTTP2
• Auth: SSL/TLS
• Open sourced: github.com/grpc/
09.03.22 Clemens Düpmeier, 09.03.22
Einsatzgebiete
• Efficiently connecting polyglot services in microservices style architecture
• Connecting mobile devices, browser clients to backend services
• Generating efficient client libraries
• Low latency, highly scalable, distributed systems.
09.03.22
Docker
CockroachDB - Super stable distributed DB CoreOS/Etcd - Distributed consistent key-value store
Google Cloud Bigtable - Sparse table storage YouTube/Vitess - Storage platform for scaling MySQL
GCE pub/sub - Google Cloud Engine Pub/Sub client
GCE Speech - Google Cloud Engine Speech client
Netflix Ribbon - Inter Process Communication library
Tensorflow - Scalable machine learning framework
Clemens Düpmeier, 09.03.22
Unterstützung zur Lösung weiterer Problemstellungen
• Tracing der Interaktion zwischen einer Vielzahl von Services – also besseres Testen von z.B. Microservice-Interaktionen
• Klare Beschreibung von APIs, deren Wechselwirkung, Weiterentwicklung APIs
• Gute Vorwärts- und Rückwärts-Kompatibilität für API-Stabilität
• Garantiere Quality of Service(QoS) Eigenschaften – Fehlertoleranz-Mechanismen
– Performance-Einhaltung
• Propagieren / Kaskadieren von Requests / Terminierung / Stop-Kriterien
09.03.22 Clemens Düpmeier, 09.03.22
Clemens Düpmeier, 09.03.22
Verteilte Objektkommunikation
Clemens Düpmeier, 09.03.22
Entfernte und lokale Methodenaufrufe
entfernter
Aufruf entfernter
Aufruf lokaler
Aufruf
lokaler Aufruf lokaler
Aufruf
• Jeder Prozess hat Objekte, einige, die entfernte Aufrufe erhalten können - entfernte Objekte genannt -, einige, die nur lokale Aufrufe erhalten können
• Objekte müssen die entfernte Objektreferenz eines Objektes in einem anderen Prozess kennen, um dessen Methoden aufrufen zu können.
Wo bekommen sie diese Referenz her ?
• Die entfernte Schnittstelle spezifiziert, welche Methoden entfernt
aufgerufen werden können
Clemens Düpmeier, 09.03.22
Eigenschaften Verteilter Objekte
• Interagierende Objekte sind auf mehr als einen Prozess verteilt
• Wichtige Begriffe (Auswahl, vereinfacht):
– Entfernte Objektreferenz: die „Adresse“/eindeutige Identität eines Objekts im ganzen verteilten System
– Entfernte Schnittstellen: die Schnittstelle eines entfernten Objekts (interface definition language, IDL)
– Ereignisse/Aktionen: Ereignisse/Aktionen von Objekten können Prozessgrenzen überschreiten
– Exceptions/Ausnahmen: verteilte Ausführung des Systems erweitert das Spektrum möglicher Fehler
– Garbage Collection: Freigabe nicht mehr benutzten Speichers wird im verteilten System schwieriger
• Über Raum und Zeit garantiert eindeutig!
• Bestehen aus
– Internetadresse: gibt den Rechner an
– Port-Nummer und Zeit: Identifizieren eindeutig den Prozess – Objektnummer: Identifiziert das Objekt
– Schnittstelle: beschreibt die entfernte Schnittstelle des Objekts
• Werden erzeugt von einem speziellen Modul - dem entfernten Referenzmodul - wenn eine lokale Referenz als Argument an einen anderen Prozess übergeben wird und in dem korrespondierenden Proxy gespeichert.
Achtung: Diese Art der Referenz erlaubt kein Verschieben des Objektes in einen anderen Prozess zur Laufzeit!
Internetadresse Port-Nummer Zeit Objektnummer Schnittstelle des entfernten Objektes
32 bits 32 bits 32 bits 32 bits
Clemens Düpmeier, 09.03.22
Entfernte Schnittstellen
• Die entfernte Schnittstelle gibt an, wie auf entfernte Objekte zugegriffen wird (Signatur der Methodenmenge).
• Ihre Beschreibung enthält
– Den Namen der Schnittstelle
– Möglicherweise Datentypdefinitionen
– Die Signatur aller entfernt verfügbaren Methoden, bestehend aus
• Dem Methodennamen
• Ihrer Ein- und Ausgabeparameter
• Ihrem Rückgabewert
• Jede Verteilte Objektkommunikationstechnologie besitzt eine
eigene Sprache, um solche Schnittstellen zu beschreiben.
struct Person {
string name;
string place;
long year;
} ;
interface PersonList {
readonly attribute string listname;
void addPerson(in Person p) ;
void getPerson(in string name, out Person p);
long number();
};
Parameter sind in, out oder inout Signatur: Definition der Methoden
CORBA hat Strukturen,
Java hat Klassen entfernte Schnittstelle
entfernte
Schnittstelle lokaler
Aufruf m1
m2 m3
m4 m5 m6 Daten
Implementierung der Methoden entfernter
Aufruf
Clemens Düpmeier, 09.03.22
Proxy Design Pattern
+request()
<<interface>>
Subject
+request() RealSubject
+request()
Proxy
realSubject
Clemens Düpmeier, 09.03.22
Bedeutung von Schnittstellen
Client Server
Gewünschte Schnittstelle
im Client
Implementierung im Server
Proxy Object (Stub)
Netzwerk
Skeleton
Kommunikationsschnittstelle
Clemens Düpmeier, 09.03.22
Teile einer Implementierung
• Kommunikationsschnittstelle: zuständig für das Request-/Reply (Anfrage-Antwort) Protokoll
• Entferntes Referenzmodul: Übersetzt zwischen entfernten und lokalen Objektreferenzen; besitzt meist eine entfernte Objekt-Tabelle, in der diese Zuordnung eingetragen wird. Beim ersten Aufruf wird die
entfernte Objektreferenz von diesem Modul erzeugt.
• Proxies und Skeletons
– Proxies (auch Stubs) genannt stellen Client Schnittstelle zur Verfügung
– Skeletons rufen serverseitige Objektimplementierung auf
Objekt A
Entferntes Referenzmodul
Kommunikations-schnittstelle
Client
Proxy B
Entferntes Referenzmodul
Kommunikations-schnittstelle
Server
Objekt B Dispatcher B
Skeleton B Request
Reply
Ausführung des
Request/Reply ProtokollsAusführung des Request/Reply Protokolls
Übersetzung zwischen lokalen und entfernten
Objektreferenzen Übersetzung zwischen
lokalen und entfernten Objektreferenzen
Proxy: schafft Transparenz für Client.
Proxy implementiert entfernte Schnittstelle.
Marshals Request und unmarshals Reply.
Leitet Request weiter.
Proxy: schafft Transparenz für Client.
Proxy implementiert entfernte Schnittstelle.
Marshals Request und unmarshals Reply.
Leitet Request weiter.
Skeleton: implementiert Methoden der entfernten Schnittstelle. Unmarshals Request und Marshals Reply. Ruft Methode in entferntem Objekt auf.
Skeleton: implementiert Methoden der entfernten Schnittstelle. Unmarshals Request und Marshals Reply. Ruft Methode in entferntem Objekt auf.
Dispatcher: wählt Methode im Skeleton aus.
Dispatcher: wählt Methode im Skeleton aus.
Clemens Düpmeier, 09.03.22
Parameterübergabe: Referenz- und Kopiersemantik
• Entfernte Methodenaufrufe sollten Parameterübergabe-Semantik der verwendeten Programmiersprache respektieren:
– In Java Übergabe von Werten per Kopie, Übergabe von Objekten per Referenz
– In C++ freie Wahl der Übergabeart
• Probleme:
– Entfernte Referenzen auf Werte prinzipiell nicht möglich
– Entfernte Referenzen auf Objekte nur möglich, wenn entsprechende Stubs und Skeletons existieren
– Empfänger benötigt Implementierungsklasse für erhaltenes Objekt (Kopiersemantik) bzw. Stub (Referenzsemantik)
Betrachte folgende Objektklasse:
import B;
public interface A extends Remote {
public void setB(B b) throws Throwable;
public B getB() throws Throwable;}}
public class AServant
extends UnicastRemoteObject implements A {
private B b;
public void setB(B b) { this.b = b;
} public B getB() { return this.b; }}
AServant
B ASkeleton
Clemens Düpmeier, 09.03.22
Parameterübergabe: Kopiersemantik (1)
Adressraum 1 Adressraum 1 Klienten-
objekt
AStub
Adressraum 2 Adressraum 2
AServant
B ASkeleton
"getB"
1. Clientobjekt hält Referenz auf Instanz von A, ruft darauf Methode getB() auf.
2. Stub übermittelt Methodenaufruf an Skeleton
3. Skeleton delegiert Methodenaufruf an Servant
4. Servant übergibt Referenz auf Instanz von B an Skeleton
Clemens Düpmeier, 09.03.22
Parameterübergabe: Kopiersemantik (2)
Adressraum 1 Adressraum 1 AStub Klienten-
objekt
Adressraum 2 Adressraum 2
AServant
B ASkeleton codierter Zustand
von B
B.jar B.jar B
5. Skeleton kodiert Zustand von Instanz gemäß Wire Protocol 6. Kodierter Zustand
wird an Stub übertragen 7. Stub lädt Klasse B,
dekodiert Zustand und erzeugt damit neue Instanz von B 8. Stub übergibt
Verweis auf neue Instanz an Aufrufer
Clemens Düpmeier, 09.03.22
Parameterübergabe: Referenzsemantik (1)
Adressraum 1 Adressraum 1 Klienten-
objekt
AStub
Adressraum 2 Adressraum 2
AServant ASkeleton
B
"getB"
1. Clientobjekt hält Referenz auf Instanz von A, ruft darauf Methode getB() auf.
2. Stub übermittelt Methodenaufruf an Skeleton
3. Skeleton delegiert Methodenaufruf an Servant
4. Servant übergibt Referenz auf Instanz von B an Skeleton
Clemens Düpmeier, 09.03.22
Parameterübergabe: Referenzsemantik (2)
Adressraum 2 Adressraum 2
AServant
B ASkeleton
Adressraum 1 Adressraum 1 AStub Klienten-
objekt
B.jar B.jar
BSkeleton (hostname, port)
BStub
5. A-Skeleton erzeugt neues Skeleton für B, falls nicht bereits vorhanden
6. A-Skeleton sendet Netzwerkadresse von B-Skeleton an A-Stub 7. A-Stub erzeugt
neuen B-Stub, der Netzwerkadresse von B-Skeleton enthält 8. A-Stub übergibt
Verweis auf B-Stub an Aufrufer
Clemens Düpmeier, 09.03.22
Weitere Aspekte der Objektübergabe
• Festlegung der Übergabesemantik i.A. durch Typ des formalen Parameters:
– Referenzen und keine Referenzen sind zunächst alles Werte! Die Übergabesemantik regelt die Art der Interpretation.
– Referenzübergabe, wenn formaler Parameter bestimmtes Interface (in Java RMI z.B.
java.rmi.Remote) implementiert – Wertübergabe sonst
• Bei Wertübergabe Komplikationen möglich:
– Wenn übergebenes Objekt direkt oder indirekt andere Objekte referenziert, müssen diese ebenfalls übergeben werden (mit welcher Übergabesemantik?)
– Sharing von Objekten muss auf der Clientseite rekonstruiert werden
– Wenn übergebenes Objekt echter Untertyp des formalen Parameters ist, ist u.U. Upcast erforderlich
• Was ist mit Garbage Collection von Serverobjekt, wenn Client Referenz darauf hat (siehe nächste Folie)?
Clemens Düpmeier, 09.03.22
Weitere Implementierungsaspekte
• Namensdienst, der Clients Objektreferenzen zunächst unabhängig von ihrer Lage vermitteln kann
• Parallele Abarbeitung: Um zu verhindern, dass ein entfernter Aufruf einen anderen Aufruf verzögert, weisen Server der Ausführung jeden entfernten Aufrufs einen eigenen Thread zu!
• Aktivierung: Automatische Erzeugung einer Instanz und Initialisierung der Instanzvariablen.
• Persistenter Objektspeicher: Verwaltet persistente Objekte, also Objekte, die zwischen Aktivierungen weiterbestehen.
• Verteiltes garbage collection: Stellt sicher, dass in einem verteilten System garbage collection durchgeführt wird. Problem: Referenzen, die nur in Nachrichten vorhanden sind.
Clemens Düpmeier, 09.03.22
Fallbeispiel(e)
Am Beispiel von Java
Clemens Düpmeier, 09.03.22
Beispiel RMI
Clemens Düpmeier, 09.03.22
RMI – Remote Method Invocation
• Definiert Verteilte Objektkommunikation von Java-Objekten unabhängig von ihrem Ort
• Eine reine Java-Lösung
• Callback Funktionalität und dynamisches Laden von Code
• Alle entfernten Objekte müssen eine entfernte Schnittstelle definiert als Java Interface abgeleitet von java.rmi.Remote besitzen
• Es sind Werkzeuge für die Generierung von Stubs und Skeletons vorhanden.
• JDK stellt eine Implementierung eines Naming-Service zur Verfügung: die RMIregistry.
• Ein RMI-Dämon erlaubt eine flexible (on-demand)-
Instanziierung (Aktivierung) von Objekten.
Clemens Düpmeier, 09.03.22
RMI Architektur
Server Programm Skeleton/Reflection Remote Reference Layer
Transport Layer
Stubs
Remote Reference Layer Transport Layer
Netzwerk
Server Client
RMI
Komponenten
Client Programm Interface
Gemeinsames
Clemens Düpmeier, 09.03.22
Remote Reference Layer (RRL)
• Stub benutzt RRL-API, um Methodenaufrufe auf die Serverseite zu übertragen
• RRL auf Serverseite benutzt Reflection oder Skeleton Objekte, um auf Serverobjekt
zuzugreifen
• RRL unterstützt unicast Punkt-zu-Punkt Objektverbindungen und aktivierbare Objekte
• Andere Formen (Multicast) sind denkbar
Clemens Düpmeier, 09.03.22
Transportlayer
• Stellt eigentliche Verbindung zwischen JVM's her – spricht JRMP (Java Remote Method Protocol) als
stream-basiertes Protokoll oberhalb von TCP/IP
• RMI ab JDK 1.3 spricht zusätzlich das RMI-IIOP
Transportprotokoll basierend auf IIOP (Internet Inter- ORB Protocol)
– ermöglicht Kommunikation zwischen CORBA und RMI Objekten
• enthält Fähigkeiten, RMI Verkehr über andere
Verbindungen zu tunneln (z.B. über HTTP)
Clemens Düpmeier, 09.03.22
Beispiel: Interfacebeschreibung eines RMI Objektes (entfernten Objektes)
• Interface von Remote ableiten
• Jeder Methode throws java.rmi.RemoteException hinzufügen
• Objekte, die so ein "Remote" Interface implementieren, sind entfernte Objekte
public interface Compute extends Remote {
<T> T executeTask(Task<T> t)
throws RemoteException;
}
Clemens Düpmeier, 09.03.22
Verwendet "normales" Objekt mit Interface Task
• Nicht-Remote Objektparameter von entfernten Methoden müssen serialisierbar sein
– Implementierungen müssen also sagen: implements Serializable
• Ein Task ist für uns ein beliebiges Objekt, dass eine execute() Methode zur Ausführung einer Berechnung besitzt und irgendein Ergebnis zurückgibt
• Objekte, die Task implementieren, sind lokale Objekte
import java.io.Serializable;
public interface Task<T> { T execute();
}
Clemens Düpmeier, 09.03.22
RMI Parameterübergabe
• Entfernte Objekte werden als Proxy (Stub) an den Client übergeben (Referenzsemantik)
– Bei Benutzung sind sowohl Methoden wie auch Daten des Objektes entfernt
• Andere (lokale Objekte) werden Call by Value (Kopiersemantik) übergeben
– Beim Kommunikationspartner wird dabei eine Kopie des Objektes angelegt
• Die Objekte müssen hierfür serialisierbar sein, um übertragen werden zu können
• Der Code muss beim Kommunikationspartner verfügbar sein oder dynamisch geladen werden
Clemens Düpmeier, 09.03.22
Implementierung des entfernten Objektes
• Implementierungsklasse wurde von UnicastRemoteObject abgeleitet; dies macht aus Objekt in Konstruktor von UnicastRemoteObject einen Server
• Konstruktor registriert Remote Objekt gleichzeitig in RMI Laufzeitinfrastruktur und macht Objekt so von aussen referenzierbar
public class ComputeEngine extends UnicastRemoteObject implements Compute
{
public ComputeEngine() throws RemoteException() { super();
}
public <T> T executeTask(Task<T> t) { return t.execute();
}
}
Clemens Düpmeier, 09.03.22
Alternative Implementierung
• Manuelles Registrieren des engine-Objektes in der RMI-Laufzeitinfrastruktur
• Laufzeitinfrastruktur liefert dabei Stub (Proxyobjekt) zurück
public class ComputeEngine implements Compute {
public <T> T executeTask(Task<T> t) { return t.execute();
} }
// und später bei Instanzierung
ComputeEngine engine = new ComputeEngine();
Compute engineStub
=(Compute)UnicastRemoteObject.exportObject(engine,0);
Clemens Düpmeier, 09.03.22
Namensauflösung bei RMI
Client System Server System
Client Programm
rmiregistry
1099
RMI Server
registry.rebind(...) registry.lookup
(liefert Stub)
Stub
rufe remote Methode
durch Stub auf
Clemens Düpmeier, 09.03.22
Registry Klasse
java.rmi.Registry
static void rebind(String name, Remote obj) // registriere
// obj im Namensdienst // mit Name name
...
static Remote lookup(String name) // hole Stub zu Name // unter Anfrage beim // Namensdienst
…
Wie sieht RMI Name aus?
//hostname[:port]/Objektname
Clemens Düpmeier, 09.03.22
Basisstruktur RMI Server (1. Version)
• Security Manager setzen = Schutz vor Clientcode
• Namen für das Serverobjekt definieren
• Serverobjekt erzeugen;
hier Version mit extends UnicastRemoteObject
• Mit Namen im rmiregistry registrieren
if (System.getSecurityManager() == null) System.setSecurityManager(new
RMISecurityManager());
String name="//hostname/Compute";
try {
Compute engineStub=new ComputeEngine();
Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, engineStub);
} catch (Exception e) { }
Clemens Düpmeier, 09.03.22
Basisstruktur RMI Server (2. Version)
• Manuelle Registrierung in der Laufzeitinfrastruktur mit exportObject()
• Man beachte: das zurückgegebene Stubobjekt und nicht engine wird im Namensdienst registriert
if (System.getSecurityManager() == null) System.setSecurityManager(new
RMISecurityManager());
String name="//hostname/Compute";
try {
ComputeEngine engine=new ComputeEngine();
Compute engineStub
= UnicastRemoteObject.exportObject(engine,0) Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, engineStub);
} catch (Exception e) { }
Clemens Düpmeier, 09.03.22
Basisstruktur RMI Client
• Security Manager setzen = Schutz vor Servercode
• Lookup des Serverobjektes im Registry
• Verwendung der Methoden des Remote Objektes
if (System.getSecurityManager() == null) System.setSecurityManager(new
RMISecurityManager());
String name="//hostname/Compute";
try {
Registry registry =
LocateRegistry.getRegistry(args[0]);
Compute engine=(Compute)registry.lookup(name);
// Methoden des Remote Objektes verwenden } catch ....
Clemens Düpmeier, 09.03.22
Basisstruktur RMI Client (2)
• Client berechnet die Zahl PI über den Server
• Hierzu muss es eine Implementierung des Task-Interfaces geben, die innerhalb ihrer execute()-Methode PI berechnet und den Wert als BigDecimal zurückgibt
...
try {
Registry registry =
LocateRegistry.getRegistry(args[0]);
Compute engine=(Compute)registry.lookup(name);
Pi task = new Pi(Integer.parseInt(args[1]));
BigDecimal pi = engine.executeTask(task);
System.out.println(pi);
} catch ....
Clemens Düpmeier, 09.03.22
Implementierung der PI-Berechnungsklasse
• zu lang für Folie
• siehe aber Java Tutorial
– enthält die komplette Implementierung des Beispiels unter
– http://java.sun.com/docs/books/tutorial/rmi/cl
ient.html
Clemens Düpmeier, 09.03.22
Wie kommt der Server zum Code der Klasse PI?
• Der jar-File mit dem Code des Servers muss nicht notwendigerweise die Klasse PI enthalten
• Wie kommt dann aber der Klassencode der Klasse PI zum Server, wenn das PI-Berechnungsobjekt zum Server
übertragen und dort ausgeführt wird?
– Java kann Code dynamisch über Netz laden!
– Hierfür muss der Code von PI irgendwo zum Download für den Server bereitgestellt werden
– Und die Infrastruktur so aufgesetzt werden, dass sie weiss,
woher der Code geladen werden soll
Clemens Düpmeier, 09.03.22
Zusammenfassung: RMI Anwendung schreiben
1. Definiere die entfernte Schnittstelle
2. Implementiere die entfernte Schnittstelle durch eine Klasse (z.B. abgeleitet von UnicastRemoteObject) 3. Generiere Stubs und Skeletons mit rmic
4. Schreibe einen Server und Client
5. Starte den Namensdienst mit rmiregistry 6. Starte den Server auf der Maschine, wo das
rmiregistry läuft
7. Starte den Client
Clemens Düpmeier, 09.03.22
RMI-Beispiel ablaufen lassen
• Vollständiger Code und Beschreibung im Java Tutorial von Sun
• Achtung: Beim Starten der Applikation (Client + Server) muss der
Klassenlader richtig aufgesetzt werden (siehe Beschreibung im Tutorial), z.B.
java -Djava.rmi.server.codebase=http://myhost/Compute/classes/ \ -Djava.rmi.server.hostname=zaphod.east.sun.com - \ -Djava.security.policy=java.policy \
ComputeEngine
da sonst die Klassen, die über Netz gehen (z.B. das Stubobjekt vom
Server, die Interfaces oder die Client Task Klasse), nicht geladen werden können
• Außerdem muss die Security-Policy Datei (wir schützen unsere
Programme von fremder Code durch SecurityManger) richtig aufgesetzt werden
Clemens Düpmeier, 09.03.22
Verteilte Objekttechnologien
Common Object Request Broker Architecture
(CORBA)
Clemens Düpmeier, 09.03.22
Object Management Group (OMG)
Distributed Component Object Model (DCOM)
• Gründung: April 1989
• Ziele:
– Interoperabilität
– Anwendungsintegration – Portabilität
• Mitglieder:
– über 800 Mitglieder
– darunter: Apple, AT&T, DEC, HP, IBM, Microsoft, SUN,...
• Entwicklungsprozeß: Request for Proposal (RFP)
in heterogenen Umgebungen
auf der Basis eines Objektmodells
Clemens Düpmeier, 09.03.22
Object Management Architecture (OMA)
• Application Objects
– spezifische Anwendungsgebiete – gehören nicht zur Infrastruktur
• Common Facilities
– allgemein nützliche Dienste (Drucken, E-Mail, Datenbanken)
– nicht notw. Teil aller Infrastrukturen
• Object Request Broker (Objektbus) – Infrastruktur für Kommunikation – garantiert Interoperabilität
• Common Object Services
– allg. Funktionen zum Erstellen u. Unterhalten von Objekten
Application Objects
Common Facilities
Common Object Services
ORB
Clemens Düpmeier, 09.03.22
ORB Aufgabe
Einbettung von Objekt-Implementationen ("Server-Objekte")
Vergabe von Objektreferenzen
Entgegennehmen von Aufrufen vom Client
Transport der Aufrufe zum Server
ggf. Aktivierung eines Server-Objektes
Übergabe des Aufrufs zum Server-Objekt
Entgegennehmen von Ergebnissen und Transport / Rückgabe zum Client
Unterstützung von Sicherheits- und Abrechnungsfunktionen
Application
Objects Common
Facilities
Common Object Services ORB
Clemens Düpmeier, 09.03.22
CORBA Protokolle: GIOP und IIOP
• Mit CORBA 2.0 wurde GIOP = General Inter-Orb Protocol als netzwerkunabhängiges Wire Protocol spezifiziert
• Die (meist verwendete) TCP/IP-Variante heißt IIOP = Internet Inter-Orb Protocol
• GIOP spezifiziert
– Nachrichtentypen (Requests, Resultate, Ping, ...)
– Datenaustauschformat ("Common Data Representation") – Interoperable Objektreferenzen (IORs)
– Service-Kontexte (Request-Anhängsel, mit denen Dienste
transparent Informationen übermitteln können)
Clemens Düpmeier, 09.03.22
Aufbau eines CORBA Servers
• POA (Portable Objekt Adapter) dient als zentrale
Zugriffsschnittstelle auf Objektimplementierungen
– erzeugt eindeutige Objektreferenzen – hat Objekt Map
– nimmt Requests für Objekte vom ORB entgegen
Netzwerk
ORB-Kern Event
Loop
Marshalling Engine
Request Interceptors für verschiedene Services (optional) ORB-
Schnittstelle
Portable Object Adapter
Fabrik für Objektreferenzen
1 2 ... ... n ...
Active Object Map Default
Servant Servant
Activator
Applikationscode
main (String args[]) { ORB orb = ORB.init(args);
orb.connect ( new AServant() );
orb.connect(
new BServant() );
orb.run();
} main (String args[]) { ORB orb = ORB.init(args);
orb.connect ( new AServant() );
orb.connect(
new BServant() );
orb.run();
}
Haupt- programm
Servant Activator
ii
Default Servant
aktive Servants
statisch (mit Skeleton)
...
dynamisch (ohne Skeleton)
Clemens Düpmeier, 09.03.22
Ablauf eines Methodenaufrufs
Client Anwendung
IDL Stub IDL Skeletton Object Adapter
Objekt
Implementierung
Implementation Repository
1) Aufruf
2) Parameter einpacken und Aufruf weiterleiten
4a) Ermitteln der Implementierung 4b) Aktivieren
5) Auspacken und Aufruf
4) Weiterleiten an Schnittstelle
Object Request Broker Core
3) Transport über den ORB mit GIOP (IIOP)
Clemens Düpmeier, 09.03.22
Object Services
Object Services
Naming
Event
Security
Transactions
Trading
Lifecycle
Time
(= Systemfunktionen)
Licensing
Properties
Relationships
Notification
Persistence
Concurrency Control
Externalisation
Nur Spezifikation der Schnittstellen und grundlegender Funktionsprinzipien!
Nur Spezifikation der Schnittstellen und grundlegender Funktionsprinzipien!
Objects Facilities
Common Object Services ORB
Clemens Düpmeier, 09.03.22
Common Facilities
• Höherwertige Dienste für ein breites Spektrum an Anwendungsbereichen
• Bereitstellung allgemein interessanter Funktionalität (analog zu großen Klassenbibliotheken)
• Horizontale Common Facilities (Basisfunktionalität allgemein)
– User Interface
– Information Management (Speicherung komplexer Strukturen, Formatkonvertierung) – Task Management (Workflow, lange Transaktionen)
– Internationalisierung („Sprachenübersetzung“)
• Vertikale Common Facilities (Basisfunktionalität speziell)
– für Marktsegemente, z.B. Banken, Gesundheitswesen, Finanzdienste – vgl. „application frameworks“, „business objects“
Application
Objects Common
Facilities
Common Object Services ORB
• Business-Objekte (M, Server)
– kapseln Speicher, Metadaten, Parallelität u. Regeln einer aktiven Business-Einheit
– legt fest, wie auf Änderungen in View/Modell reagiert wird
• Business-Prozeßobjekte (C, Server) – kapseln Business-Logik
– Verwaltung vorwiegend langlebiger Prozesse (Workflow, Transaktion)
• Präsentationsobjekte (V, Client)
– grafische Darstellung des Objektes
– unterschiedliche Präsentationen möglich
Andere
Business-Objekte Dokument Server Business-
Objekt Business-
Prozeß- Objekt
Präsentations- Objekt
Komponenten eines Business-
Objektes Andere Schnittstellen
MVC MVC MVC MVC
Common Object Services
Clemens Düpmeier, 09.03.22
IDL (Interface Definition Language)
• Basismechanismus zur Definition von Schnittstellen (Standard)
• Unabhängig von spezieller Sprache (dekla-rativ, d.h. ohne algorithmische Teile, d.h. ohne
Implementierungsdetails)
• Sprachbindung für verschiedene Sprachen
• IDL-Grammatik ist Teilmenge von C++; zusätzlich Mittel für Verteilungskonzepte
• Beinhaltet Mehrfachvererbung
• Schnittstellenverzeichnis (Interface Repository), damit selbstbeschreibend
• IDL ist Kontrakt, der alle und alles zusammenbringt
C
C++
Smalltalk Ada
COBOL
Java
IDL IDL IDL IDL IDL IDL
ORB
Clemens Düpmeier, 09.03.22
Beispiel für eine IDL Datei (1)
module Bank {
typedef sequence<string> StringArray;
struct Person {
string name;
string vorname;
};
// hier fehlt noch exception Definition interface Konto {
readonly attribute float kontostand;
readonly attribute long geheimzahl;
readonly attribute long kontonummer;
void einzahlen(in float betrag);
void abheben(in float betrag);
void unlock(); // Sperre freigeben };
// hier geht es weiter mit dem KontoManager };
Clemens Düpmeier, 09.03.22
Beispiel IDL Datei (2)
module Bank {
typedef sequence<string> StringArray;
struct Person {
string name;
string vorname;
};
exception KontoException { string begruendung;
};
// hier war interface Konto definiert interface KontoManager {
Konto anmelden(in long kontonr, in long geheimzahl) raises (KontoException);
Konto oeffnen(in Person daten);
void aufloesen(in Konto konto);
StringArray holeKontenInfos();
};
};
Clemens Düpmeier, 09.03.22
Feature der IDL (1)
• Mehrere Interface Beschreibungen können in einer Modulbeschreibung zusammengefasst werden
• Es gibt die von anderen Sprachen bekannten Standardtypen (Gleitkomma, Integer, Zeichen-, bool, Byte und deren
Subtypen)
• Es gibt Konstrukte zum Aufbau von struct's und union's
• Template Typen sequence und string sowie Arrays
• Neue Typen können mit typedef deklariert werden
• interface Definitionen entsprechen neu definierten Objekttypen (Klassen)
• Es gibt den Begriff Attribut mit name() und name(value)
Zugriffsfunktionen
Clemens Düpmeier, 09.03.22
Feature der IDL (2)
• Es gibt Enumerations (Aufzählungstypen)
• Man kann Konstanten deklarieren
• Weiter gibt es Exception Deklarationen für Ausnahmezustände
• Parameter von Methoden lassen sich als in, out oder inout Parameter definieren
• Weiter gibt es die Möglichkeit Methoden als vom Typ oneway
(d.h. kein Returnwert erwartet) zu deklarieren, was eine nicht-
blockierende Bearbeitung bedeutet (der Client wartet hier
nicht auf den Server)
IDL-C++
Compiler IDL-C++
Compiler Schnittstellendesigner
interfaces.idl interfaces.idl
types.hh
types.hh stubs.cc stubs.cc skels.cc skels.cc
Programmierer
servants.cc servants.cc Server
IDL-Java Compiler IDL-Java Compiler
stubs.jar stubs.jar Anwendungsentwickler
client.jar client.jar
Client
Clemens Düpmeier, 09.03.22
RMI-IIOP
Corba Objekte mit RMI
Clemens Düpmeier, 09.03.22
Beispiel-Interface
• Ganz normales RMI Interface
//HelloInterface.java import java.rmi.Remote;
public interface HelloInterface extends java.rmi.Remote {
public void sayHello( String from )
throws java.rmi.RemoteException;
}
Clemens Düpmeier, 09.03.22
Implementierung des Interfaces
• Leitet von PortableRemoteObject ab!
//HelloImpl.java
import javax.rmi.PortableRemoteObject;
public class HelloImpl extends PortableRemoteObject
implements HelloInterface { public HelloImpl() throws java.rmi.RemoteException {
super(); // invoke rmi linking and remote object initialization }
public void sayHello( String from ) throws java.rmi.RemoteException {
System.out.println( "Hello from " + from + "!!" );
System.out.flush();
} }
Clemens Düpmeier, 09.03.22
RMI-IIOP Serverprogramm
//HelloServer.java
import javax.naming.InitialContext;
import javax.naming.Context;
public class HelloServer {
public static void main(String[] args) { try {
HelloImpl helloRef = new HelloImpl();
// Step 2: Publish the reference using JNDI API
Context initialNamingContext = new InitialContext();
initialNamingContext.rebind("HelloService", helloRef );
} catch (Exception e) { e.printStackTrace();
} }
}
Clemens Düpmeier, 09.03.22
RMI-IIOP Clientprogramm
public class HelloClient {
public static void main( String args[] ) { Context ic; Object objref;
HelloInterface hi;
try {
ic = new InitialContext();
hi = (HelloInterface)ic.lookup("HelloService");
hi.sayHello( " MARS " );
} catch( Exception e ) {}
} }