Preview only show first 10 pages with watermark. For full document please download

Verteiltes Rechnen Mit Rmi

   EMBED


Share

Transcript

Verteiltes Rechnen Verteilte Dienste mit Java Remote Method Invocation (RMI). Prof. Dr. Nikolaus Wulff Verteiltes Rechnen • Anwendungen im WWW sind meist als Client-Server Architekturen realisiert. • Ein Client stellt Anfragen an einen entfernten Server. – Per HTTP meistens als „primitive GET-Request“ mit einem HTML Dokument als Rückgabewert. – Programmierung „auf dem Draht“ mit primitiven Datenstrukturen per Java (Server)Sockets. • Java bietet zusätzlich die Möglichkeit höherwertige Dienste als echte Java Objekte anzusprechen. – HTTP basierte Web-Services via XML/SOAP und WSDL. – Remote Method Invocation (RMI) mit Java generierten Proxy und Adapter Klassen für Client und Server. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 2 Verteilung und Nebenläufigkeit • Neben des grundsätzlichen Vorteils, dass Client und Server auf physisch getrennten Maschinen laufen, bietet eine solche Architektur die Möglichkeit der Parallelisierung und Lastverteilung. • Der Preis hierfür ist der Geschwindigkeitsverlust durch die Netzzugriffe und eine anfängliche Lernkurve zum Erlernen dieser Technologie(n). • RMI beinhaltet alle wesentlichen Bestandteile, die auch in den weiterführenden J2EE Architekturen – wie EJB oder Web-Services – Verwendung finden. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 3 Architekturblaupause • Der Service wird als (Java) Schnittstelle beschrieben. • Serverseitig wird dieser Dienst implementiert. • Der Client bekommt mit Hilfe eines Stellvertreterobjekts eine Referenz auf eine Implementierung der Schnittstelle. • Ein Naming-Service bietet eine Art „Telefonbuch“ (Yellow Pages) für registrierte Dienste an. • Serverseitig registrieren sich die Dienste beim Naming-Service, clientseitig werden sie gesucht. • Client- und serverseitige Hilfsklassen werden passend zur Schnittstellenbeschreibung mit RMIC generiert. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 4 HelloWorld Pseudo Code • Lokaler Methodenaufruf: dauert ~ 1 - 4 NanoSec HelloInterface h = new HelloImpl(); h.sayHello("HelloWorld"); • Remote Methodenaufruf: dauert ~ 5 - 50 MilliSec !!! HelloInterface h = HelloFactory.lookup("myServer","myObject"); h.sayHello("HelloWorld"); © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 5 RMI Architektur Remote Interface Client Application RMI Stub Class Remote Object Skeleton Class Remote Reference Layer Transport Layer (JRMP) © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 6 HelloWorld mit RMI RMI Framework java.rmi.* generated by RMIC Developer defined © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 7 RMIC Generierung • Seit JDK1.2 werden keine Quelltexte für die Stubund Proxy Klassen mehr auf der Platte oder im Archive gespeichert. • Mit den RMIC Parameter -v1.1 und -v.1.2 lässt sich steuern für welches RMI Protokoll generiert wird. • Werden beim Aufruf von RMIC die Parameter -keepgenerated übergeben, so ist es möglich den Quelltext dieser Klassen zu studieren. – Seit 1.2 wird die java reflection API eingesetzt. – -v1.1 generiert @deprecated Code. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 8 Implementierung des Service public class HelloImpl extends UnicastRemoteObject implements HelloInterface { /** * Sole constructor. * @throws RemoteException during remote IO binding */ protected HelloImpl() throws RemoteException { super(); } © /* (non-Javadoc) * @see de.lab4inf.rmi.HelloInterface#sayHello(java.lang.St */ @Override public String sayHello(String msg) throws RemoteException { String ret = format("[%s %s] msg: %s",this, Thread.currentThread(),msg); System.out.printf("sayHello %s\n",ret); return ret; } Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 9 Gelbe Seiten • Im Laufe der Zeit haben sich die Anforderungen an die Registrierung von RMI Objekten verändert. Es gibt inzwischen: • Die java.rmi.registry.Registry • Den java.rmi.Naming Service • Und für Enterprise Anwendungen den JNDI – Verzeichnisdienst das Java Naming and Directory Interface, das in J2EE Anwendungen verwandt wird. • Der Zweck bleibt gleich: Registriere ein Objekt unter einer URL (bind) und mache es auffindbar im Netz per (lookup)... © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 10 HelloClient mit RMI public static void main(java.lang.String[] args) throws Exception { String url = “//localhost/hello“; // 1. Referenz auf den Server per Naming Service System.out.println("Suche Server "+url); Remote ref = Naming.lookup(url); // 2. Cast auf den gewünschten Typ HelloInterface hello = (HelloInterface) ref; System.out.println("Fand "+hello); // 3. Remote Call ausführen long time = System.currentTimeMillis(); hello.sayHello("Hello vom HelloClient "+time); System.out.println("done ..."); } © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 11 Service Registrierung public class HelloImpl extends UnicastRemoteObject implements HelloInterface { // ... public static void main(java.lang.String[] args) throws Exception { String url = “//localhost/hello“; // 1. Server Instanz erzeugen System.out.println("Erzeuge Server"); HelloInterface hello = new HelloImpl(); // 2. Server Instanz beim Naming Service bekannt machen System.out.println("Registriere Server "+hello); Naming.rebind(url,hello); System.out.println("Server "+url+" ready... “); } © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 12 Testlauf Wichtig: Vor dem Start des Servers muss die rmiregistry mit entsprechendem Classpath gestartet sein, sonst schlägt die Registrierung der Serverinstanz fehl. $ java de.lab4inf.rmi.HelloImpl verteilt Erzeuge Server multi-threaded Registriere Server HelloImpl [UnicastServerRef [liveRef: [endpoint: [127.0.1.1:48796](local),objID: [3ffe7dc9:134eaef05ce:-7fff, 6082581128767713112]]]] Server rmi://localhost/hello ready... sayHello [HelloImpl[UnicastServerRef [liveRef: [endpoint:[127.0.1.1:48796](local),objID: [3ffe7dc9:134eaef05ce:-7fff, 6082581128767713112]]]] Thread[RMI TCP Connection(2)-127.0.0.1,5,RMI Runtime]] msg: Hello vom HelloClient 1326791465704 © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 13 Generierter Stub public final class HelloImpl_Stub extends java.rmi.server.RemoteStub implements de.lab4inf.rmi.HelloInterface, java.rmi.Remote { private static final long serialVersionUID = 2; private static java.lang.reflect.Method $method_sayHello_0; de.lab4inf.rmi-Packagename entfernt ... static { try { $method_sayHello_0 = HelloInterface.class.getMethod("sayHello", new java.lang.Class[] {java.lang.String.class}); } catch (java.lang.NoSuchMethodException e) { throw new java.lang.NoSuchMethodError("stub class initializ } } • Der generierte Code verwendet die Reflection API, um die Methodenzeiger zu finden/setzen.... © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 14 Delegation an die Implementierung // methods from remote interfaces // implementation of sayHello(String) public java.lang.String sayHello(java.lang.String $param_String_1) throws java.rmi.RemoteException { try { Object $result = ref.invoke(this, $method_sayHello_0, new java.lang.Object[] {$param_String_1}, 8370655165776887524L); return ((java.lang.String) $result); } catch (java.lang.RuntimeException e) { throw e; } catch (java.rmi.RemoteException e) { throw e; } catch (java.lang.Exception e) { throw new java.rmi.UnexpectedException("undeclared checked exceptio } } • Und per Reflection wird die implementierende sayHello-Methode gerufen.... © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 15 RMI wozu...? • Mit RMI ist es möglich objektorientiert Dienste verteilt anzubieten. • Z.B. einen Script-Parser, den Differentiator oder …, so dass rechenintensive Arbeiten auf entfernten leistungsstarken Maschinen ausgeführt werden. • Wird dies zusätzlich mit dem „Divide and Conquere“ Ansatz durchgeführt, so ist es möglich paralleles Rechnen auf verteilten Maschinen durchzuführen. • Dies lohnt sich immer dann, wenn der Zeitverlust durch die Verteilung der Daten per Netz-IO geringer ist als der Performanzvorteil der Parallelisierung. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 16 RMI Pragmatik • Es ist wichtig bei verteilten Anwendungen die richtige Granularität der Aufrufe zu finden. • Viele „kleine, verteilte“ Getter/Setter-Methoden bremsen eine verteilte Anwendung komplett aus! • Daher „Datenobjekte“ als verteilbare Container für RMI Argumente verwenden. Diese sind dann meist serialisierbar, werden „in einem Rutsch übertragen“ und für Enterprise-Anwendungnen zumeist generiert. • Entsprechende Werkzeuge, wie z.B. XDoclet, Spring und Hibernate unterstützen dies und es gibt zahlreiche Architekturblaupausen für verteilte Anwendungen. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 17 Zusammenfassung • Java bietet mit den RMI Paketen eine Möglichkeit verteilte objektorientierte Anwendungen mit einfachen Mitteln zu entwickeln. • Gegen eine Remote-Schnittstelle werden automatisch Client-Proxies und Server-Adapter generiert. • Ein Naming-Service liefert „Gelbe Seiten“. • Lastverteilung und höherwertige Dienste wie z.B. Autorisierung, Sicherheit, Transaktionen etc. fehlen. • Diese Dienste werden mit der Java Enterprise Edition (J2EE) zur Verfügung gestellt. © Prof. Dr. Nikolaus Wulff Höhere Programmierkonzepte 18