Projektstudium SS98 - distributed computing


vorherige Seite Inhalt nächste Seite

Architektur des RMI Systems

Das RMI System besteht aus drei vollständig unabhängigen, eigenständigen Schichten: der stub/skeleton-layer, der remote reference-layer, und der transport-layer.

Die Kommunikation erfolgt im RMI automatisch über fest definierte Protokolle, so daß es auch stets möglich ist eine komplette Schicht auszutauschen. Z.B. kann die derzeit auf TCP basiernde Transportschicht evtl. durch eine andere Transportschicht ersetzt werden, die ein anderes Protokoll realisiert, z.B. UDP.

Die Zuordnung von Client- und Serverfunktion gilt stets nur für eine konkrete Kommunikation zweier Objekte. Somit kann ein Objekt Client bzgl. eines Zugriffs auf ein entferntes Serverobjekt sein und danach einen Serverdienst für ein anderes Objekt erbringen, welches auf einem anderen, entfernten Rechner existiert.

Der Aufruf einer entfernten Methode läuft nun von der Applikationsschicht des Clients hinunter durch die Schichten des RMI Systems zur Transportschicht, wird dann zum Server übertragen, und durchläuft serverseitig wieder durch die Schichten des RMI Systems, um vom Server abgearbeitet zu werden.

Die Stub/Skeleton Schicht

Die Stub/Skeleton-Schicht ist das Interface zwischen der Applikationsschicht und dem RMI System, sie kümmert sich nicht um spezielle Details des Datentransports, sondern überträgt die Daten zur und von der Remote Reference Schicht durch das Prinzip des "parameter marshalling". Wenn von einem Objekt im Client eine Methode eines Serverobjekts aufgerufen werden soll, bzw. dem Serverobjekt eine Nachricht gesendet werden soll, wird ein lokales Stellvertreterobjekt verwendet, welches als Stub bezeichnet wird. Dieses existiert im Adressraum der JVM die das Client-Objekt ausführt und stellt somit für die restliche Applikation ein reguläres Java-Objekt dar. Der Stub implementiert die Interfaces, welche auch vom entfernten Objekt unterstützt werden.

Auf der Serverseite empfängt das entfernte Stellvertreterobjekt des eigentlichen Remote-Objektes, bezeichnet als Skeleton, über die dortige Remote Reference Schicht den Datenblock und ruft die gewünschte Methode des Serverobjekts auf. Rückgabewerte, wozu auch ausgelöste Ausnahmeobjekte (Exceptions) gehören, werden auf analogem Weg zum Client zurückgesendet.

Die passenden Stub- und Skeleton Klassen werden zur Laufzeit bestimmt und dynamisch geladen(Dynamic class loading).

Da ein generelles Ziel vom RMI System eine nahtlose Eingliederung des APIs in die reguläre Sprache ist, kann der Entwickler die Remote-Objekte (fast) genauso verwenden wie originäre Java-Objekte. Damit ist auch klar, daß der oben beschriebene komplexe Kommunikationsweg vollständig transparent und vom RMI automatisiert ist.

Die Remote Reference Schicht

In dieser Schicht wird die Kommunikation mit der Transportschicht geregelt und im wesentlichen das Protokoll bestimmt, nach dem die entfernten Referenzen zugeordnet werden. Dies geschieht unabhängig von den Stub- und Skeleton-Objekten.

Jede Implementierung eines entfernten Objekts bestimmt die Art der Referenzierung. Es können verschiedene Aufrufprotokolle in dieser Schicht umgesetzt werden:

  • Einfacher Methodenaufruf bei einer Punkt-zu-Punkt Zuordnung
  • Methodenaufruf von replizierten Objekten
  • Unterstützung spezieller Replikationsstrategien
  • Unterstützung dauerhafter Referenzen zum entfernten Objekt
  • Strategien zur Wiederverbindung bei einer unterbrochenen Verbindung zum Objekt
Es gibt zwei Komponenten bzgl. der Client- und Serverseite, die bei der Methodenausführung miteinander kooperieren. Die Client-Komponente enthält die relevanten Informationen über die Serverimplementierung des Objekts und kommuniziert über die Transportschicht mit der serverseitigen Komponente. So kann z.B. bei einem replizierten Server-Objekt der Methodenaufruf an alle Kopien weitergeleitet werden. Die Komponente der Remote Reference Schicht auf der Serverseite dient der Weiterleitung des Aufrufs an das Skeleton-Objekt.

Die Remote Reference Schicht sendet die Daten, durch abstrakte, streamorientierte Verbindungskanäle, zur Transportschicht. Und obwohl eine Verbindung durch Streams zustande kommt, kann die Verbindung durch die Abstraktion transparent implementiert werden.

Die Transport-Schicht

In der Transportschicht werden die folgenden Aufgaben wahrgenommen:

  • Aufbau, Verwaltung und Überwachung von Verbindungskanälen zu entfernten Adressräumen
  • Verwaltung einer Tabelle der entfernten Objekte die sich im lokalen Adressraum befinden
  • Annahme von Verbindungswünschen anderer und Aufbau der Verbindungskanäle

Die Übertragung im RMI System geschieht mit Hilfe von vier grundlegenden Abstraktionsarten:

  • Ein endpoint ist die Abstraktion um eine JVM bzw. einen Adressraum zuzuordnen. (In der Implementation kann ein endpoint auf den Übertragungskanal abgebildet werden. D.h. bei einem gegebenen endpoint, kann eine definierte Übertragungsinstanz erzeugt werden.)
  • Ein channel ist die Verallgemeinerung für eine virtuelle leitungsgebundene Verbindung zweier Adressräume. Der Kanal ist für die Verwaltung der Verbindung des lokalen und entfernten Adressraumes verantwortlich.
  • Eine connection ist die Abstraktion für eine bidirektionale Datenübertragung
  • Ein transport ist die Abstraktion für die Verwaltungsinstanz der Kanäle (channels). In jedem transport kann nur ein Kanal für zwei Adressräume real aufgebaut werden. Eine Zuordnung eines endpoints zu einem entfernten Adressraum bewirkt einen Verbindungsaufbau (Kanal). Weitere Aufgaben sind die Annahme von eingehenden Aufrufen, der Einrichtung einer Verbindung und der Weiterleitung zu der höheren Systemebene.

Die konkrete Repräsentierung eines entfernten Objekts, bezeichnet als live reference, besteht aus einem endpoint und einer eindeutigen Identifikation (Schlüssel) des Objekts. Mit einer solchen live reference kann in der Transportschicht im Client per endpoint die Verbindung zum entfernten Adressraum aufgebaut, sowie auf der Serverseite das konkrete Objekt durch den Schlüssel bestimmt werden.

Ein transport definiert wie eine konkrete Repräsentation eines endpoits aussieht, d.h. es können verschiedene Übertragungsmöglichkeiten implementiert werden, so daß mehrere Protokolle (TCP und UDP) in derselben JVM unterstützt werden können. Das RMI Transport Interface ist jedoch nur für die Implementation der VM verfügbar, und nicht direkt für die Applikation.

Dynamic Class Loading

Ein Client im RPC-Umfeld benötigt kompilierten Code für Stubs, der statisch oder dynamisch (über lokale Bibliotheken oder ein Netzwerk-Filesystem) zum aktuellen Programm gebunden wird, bevor die Routine ausgeführt werden kann.

RMI generalisiert diese Technik dahingehend, daß

  • neutraler Bytecode verwendet wird, da dies ein wesentliches Merkmal der Sprache ist. Dies ermöglicht bzw. vereinfacht den heterogenen Mix von Client- und Serverplattformen.
  • wahlfreies Laden von Klassen von lokalen oder entfernten Quellen möglich ist, indem ein spezieller RMIClassLoader zur Verfügung gestellt wird. Neben den anderen Möglichkeiten in Java (AppletLoader, Classpath), ist damit eine Kontrolle und genaue Steuerung der Klassenherkunft möglich.
  • automatisches Laden von fehlenden Class-Files zur Laufzeit
    • Von entfernten Objektklassen und Interfaces
    • Von Stub und Skeletonklassen
    • auch von anderen, in der RMI-Anwendung, benötigten Klassen, wie z.B. Parametern von Methoden oder Rückgabeobjekte.

Zusätzlich zu den Class Loadern benutzt das dynamic class loading weitere Mechanismen, wie die Objekt Serialisation, um die Klassen über das Netz zu übertragen, sowie einen Security Manager der die geladenen Klassen überwacht. (--> Security)

Garbage Collection von entfernten Objekten

In einem verteilten System, genau wie in einem lokalen System, ist es wünschenswert, entfernte Objekte die nicht mehr referenziert werden, automatisch zu löschen. Das befreit den Programmierer von der Verfolgung der entfernten Objekte, um sie manuell zu entfernen, damit das Programm sauber beendet werden kann.

Um die garbage collection aller Objekte zu ermöglichen, muß das RMI System zur Laufzeit alle live references innerhalb jeder JVM verfolgen. Wenn eine live reference in eine JVM eintritt, wird ihr Referenzzähler erhöht. Die erste Referenz eines Objekts sendet eine "referenzierte" Nachricht an den Server des Objekts. Durch die Beendigung einer live refernce in der lokalen VM, wird der Referenzzähler erniedrigt. Wenn nun auch die letzte Referenz entfernt wurde, wird eine "unreferenzierte" Nachricht an den Server geschickt. Wie bei dem Lebenszyklus eines normalen Objekts, wird die Methode finalize aufgerufen, nachdem der Garbage Collector festgestellt hat, daß keine Referenzen, weder lokal noch entfernt, auf das Objekt existieren.

Natürlich ist es im Netzzugriff nicht immer möglich, daß eine entfernte Objektreferenz aufgelöst werden kann (durch Netzwerkausfall), wenn dann versucht wird eine solche Referenz zu benutzen, wird eine RemoteException ausgelöst.

Security und Firewalls

Im Bereich der Netzwerkanwendungen ist stets die Möglichkeit gegeben, daß Mißbrauch mit den Zugriffsmöglichkeiten betrieben wird. In dem konkreten Fall der verteilten Anwendungen ist eine Steuerung und Kontrolle der entfernten Methodenaufrufe notwendig. Das RMI-System bietet ein Standardsicherheitssystem an, den RMISecurityManager. Dieser muß in Applikationen als erstes gestartet werden, um die Kontrolle über die über Netz gehenden Methodenaufrufe zu erhalten und entscheiden zu können, welche Stub-Klassen von welchen Servern geladen werden dürfen. Auch kann dadurch kontrolliert werden, was Stub-Objekte, die ja im Adressraum des Clients ausgeführt werden, dürfen, z.B. Zugriff auf lokale Ressourcen (Festplatte, etc.) und Zugriff auf andere Server.

Werden RemoteObjects über Applets geladen, so übernimmt standardmäßig der Applet Security-Manager die Kontrolle. Es ist weiterhin möglich eigene Security-Manager zu implementieren, die speziell applikationsgebundene Sicherheitsbelange unterstützen. Wenn kein Security Manager spezifiziert wird, können keine Klassen über das Netz geladen werden.

Zudem ist seitens des Designs und der Entwicklung steuerbar, welche (entfernte) Objekte über das Netz transportiert werden können. Dies kann nur mit Objekten geschehen, die serialisierbar sind, also das Interface Serializable implementieren. Dies kann jedoch für jedes Applikationsobjekt selbständig deklariert werden.

Normalerweise versucht die RMI Transportschicht direkte Socketverbindungen zu anderen Hosts zu öffnen, jedoch gibt es viele Hosts die dieses durch eine Firewall verhindern. Für diesen Fall besitzt das RMI System zwei alternative HTTP-basierende Mechanismen, die es einem Client hinter einer Firewall erlauben, Methoden eines entfernten Objekts außerhalb dieser Firewall aufzurufen (POST-Anfragen oder Firewall -tunneling durch RMISocketFactory).

vorherige Seite Inhalt nach oben nächste Seite
© Copyright 1998 André Möller, Oliver Mentz & Magnus Wiencke