Java RMI - ssw.jku.at

Werbung
Java RMI – Remote Method Invocation
Ziel: Aufruf von Instanzmethoden entfernter Objekte basierend auf
Java.
Paket: java.rmi und Unterpakete
Topologie:
RMI Registry
RMI Server
RMI Client
Der Server registriert in der Registry Objekte, deren Methoden von
entfernten Clients aufgerufen werden können.
Registry ist Name Service, d.h. Abbildung von Name auf Objekt.
Der Client führt ein Lookup in der Registry nach einem bestimmten
Namen durch und erhält Stub des entfernten Objekts als Ergebnis.
Anschließend kommuniziert der Client direkt mit dem Server durch
Aufruf von Stub-Methoden. Diese werden über das Netz zur Server
geschickt und dort ausgeführt. Das Ergebnis kommt wieder über
das Netz zum Client.
Aufrufe sind synchron, d.h. Client wartet auf das Ergebnis.
Registry kann in Serverprozess sein oder separate JVM.
Registry verwendet TCP/IP-Port zur Kommunikation mit Server und
Client.
Remote Object verwendet eigenen TCP/IP-Port zur Kommunikation
mit Client.
Hinweis: bei Verwendung von Firewalls kann es sein, dass diese
Ports gesperrt sind -> Firewall umkonfigurieren.
Entfernte Objekte
Schnittstelle für entfernte Objekte definiert durch Interface.
Diese Schnittstelle erweitert java.rmi.Remote.
Alle Methoden werfen potentiell RemoteException.
Beispiel:
import java.rmi.*;
public interface HelloWorld extends Remote {
String sayHello() throws RemoteException;
}
Serverseitig wird dieses Interface durch eine Klasse implementiert,
die von UnicastRemoteObject erbt und die Schnittstelle
implementiert.
public class HelloServer
extends UnicastRemoteObject implements HelloWorld {
public String sayHello() throws RemoteException {
return "Hello World";
}
}
Start der Registry lokal in Server mittels Hilfsklasse
LocateRegistry. Könnte auch zum Zugriff auf externe Registry
verwendet werden.
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
Registry reg = LocateRegistry.createRegistry(1099);
Registrieren eines Server-Objektes mit bind (oder rebind).
reg.bind("HelloServer", new HelloServer());
Erzeugen einer stub-Klasse für entfernte Klienten aus
HelloServer.java mittels Commandline-Tool rmic.
rmic HelloServer -d targetDir
Die erzeugt Stub-Klasse muss im Klassenpfad des Clients
verfügbar sein.
Lookup von HelloServer in Client z.B. mittels RMI Pseudo URL:
rmi://rmireghost:rmiregport/name.
HelloWorld helloStub =
(HelloWorld)java.rmi.Naming.lookup(
"rmi://localhost:1099/HelloServer");
Verwenden des entfernten Objekts durch Methodenaufrufe.
System.out.println(helloStub.sayHello());
Zur Übersetzung des Clients wird die Schnittstelle HelloWorld
benötigt.
Zur Ausführung wird HelloWorld und die Stub-Klasse benötigt.
Serialisierung der Methodenaufrufe
Um einen Methodenaufruf über das Netzwerk zu transportieren
erfolgt eine Serialisierung aller Parameter.
=> Alle Parameter müssen serialisierbar sein.
Serialisierung ergibt Kopie der Paramter beim Empfänger.
Pointeridentität innerhalb der Parameter garantiert.
Parameter vom Typ Remote (z.B. UnicastRemoteObject)
werden speziell behandelt: Es wird eine serialisierte Objektreferenz
übertragen, nicht der Inhalt. Solche Objekte müssen nicht über die
RMI Registry registriert werden.
Die RMI-Registry verwendet diesen Mechanismus selbst. Die
Registry ist ein Client für alle registrierten Objekte.
Der Empfänger verwendet Remote Objekte via RMI, ausser das
Objekt ist im Empfänger implementiert.
Symmetrie: Ein Client kann zusätzlich auch Server sein und
umgekehrt.
Verteilte Garbage Collection
Prinzip der automatischen Speicherbereinigung bei RMI
beibehalten durch verteilte GC via Reference Counting und Leases.
Server merkt sich exportierte Objekte und Zeit für letzte
Verwendung (Lease start).
Client merkt sich importierte Objekte und sendet periodisch LeaseRenewal Messages zum Server.
Stirbt der letzte Client eines Objekts, so folgen keine Renewal
Messages und das Objekt wird nach timeout am Server gelöscht.
Typische Lease-Intervalle sind 10 Minuten. Nach 5 Minuten
versucht der Client einen Lease-Renewal. Bei Fehlschlag folgen
einige Wiederholungen.
Durch null-Setzen von Referenzen plus GC in Client kann Freigabe
von Objekten am Server beschleunigt werden.
Threading Modell
RMI Server können von mehreren Clients parallel verwendet
werden.
Jeder Request läuft in eigenem Thread ab.
Synchronisierung der Server-Operationen beachten!
Bezug zu Projekt
zentrales Modell als RMI remote Object implementieren.
JavaBeans Event Pattern berücksichtigen.
Lokales Modell wirkt als Bridge für entferntes Modell.
registriert (Remote)Listener bei zentralem Server-Objekt.
zentraler Server notifiziert remote Clients bei Änderungen.
Views verwenden weiterhin lokales Modell wie in lokaler Lösung.
Ein Client wird zu irgendeiner beliebigen Zeit notifiziert und dazu
am Client ein eigener Thread gestartet. Dieser darf nicht direkt mit
Swing arbeiten.
Synchronisierung mit Swing event-dispatcher thread durch
Registrierung einer Aktion (Runnable), die von Swing aus gestartet
wird.
javax.swing.SwingUtilities.invokeLater(
new Runnable() {
public void run() {
fireEvent(e);
}
});
Class Loader und Security
Java RMI erlaubt das Nachladen von Klassen zwischen Server und
Client (beide Richtungen), also ausserhalb des normalen
CLASSPATH.
Das ist aus Sicherheitsgründen normalerweise in Java nicht
erlaubt.
Abhilfe: Setzen eines geeigneten SecurityManagers (oder alle
Klassen über CLASSPATH verfügbar machen).
System.setSecurityManager(new RMISecurityManager());
Socket Factories
Der RMI-Mechanismus verwendet normalerweise TCP/IP Sockets.
Erweiterungen (Spezialisierungen) von RMI sind möglich durch
Implementierung eigener SocketFactories.
Eine global verankerte SocketFactory wird von RMI verwendet, um
Sockets zu erzeugen.
Spezielle SocketFactory könnte zum Beispiel Request via http oder
https transportieren oder einen ganz andern Transport Layer
verwenden.
SSL und Routing über http bzw. https wird bereits in Java2 RMI
unterstützt.
Hinweis: http/https sind one way, also nur Client -> Server.
Herunterladen