Softwareentwicklung in verteilten Umgebungen, Teil 5 Middleware (Coulouris et al., Kapitel 5) Dieter Schmalstieg Partly based on material by Victor García Barrios
Warum Middleware? TCP/IP hat niedrige Software-Abstraktion Typisches Request-Reply-Protokoll while(true) { switch(message_type) {... }} case MESSAGE1:... case MESSAGE2:... Keine bequeme Einbettung in Software- Entwicklung Middleware bietet höherwertige Dienste an
Middleware im Layer-Modell
Konkrete Teile einer Middleware Applications RMI, RPC and events Request reply protocol Middleware layers External data representation Operating System
Typische Dienste der Middleware Kommunikation mit Access Transparency Directory Service Ortstransparenz Transaktionsunterstützung Komponentenmanagement, Instantiierung Persistenz Installation (Deployment) Fehlertoleranz Sicherheit, Authentifizierung
Middleware-Ansätze Verteiltes Dateisystem Verteilte Dokumente (Web) Remote Procedure Call (RPC) Remote Method Invocation (RMI) Verteilte Event-Systeme, Publish-Subscribe Message-oriented middleware Streaming media
Remote Procedure Call Explizite Messages: Keine Kommunikations- Transparenz Besser: Einbettung in Programmiersprache System verbindet Aufrufer und Prozedur Fehlerbehandlung durch Sprach-Exceptions
Was passiert bei normalem Procedure Call? Kopieren der Parameter auf Stack Parameter1 Parameter2... ParameterN Return-Address Jump-to-Subroutine Lokale Variablen auf den Stack Execute Return Value auf Stack Return to Caller
Einfacher RPC-Ablauf Wie erfolgt die Verbindung Client-Server? Wie werden Parameter übergeben? C lie n t p r o z e s s S e r v e r p r o z e s s C lie n t p r o z e d u r S e r v e r p r o z e d u r C lie n t - S t u b - P r o z e d u r S e r v e r - S t u b - P r o z e d u r
M a rs h a lin g / U n m a rs h a lin g P ro z e d u re n M a rs h a lin g / U n m a rs h a lin g P ro z e d u re n Stubs Zugriffsschnittstelle entkoppelt Client & Server Code aus Schnittstellenspezifikation generiert Verantwortlich für Marshalling/Unmarshalling Ermöglichen von Zugriffs- und Ortstransparenz S e r v e r - m a in P r o z e d u r C lie n t - m a in P r o z e d u r S e r v e r - P r o z e d u r C lie n t - S t u b P r o z e d u r e n S e r v e r - S t u b P r o z e d u r e n D is p a t c h e r P r o t o k o lls t a c k v e r t e ilt e s S y s t e m
Interface Definition Language (IDL) Sprachunabhängige Definition von remote aufrufbaren Prozeduren Definition von universalen Datentypen IDL Compiler erzeugt Client und Server Header Files und Stub Code Client-Code inkludiert Client-Header, linkt Client-Stub Server-Code inkludiert Server-Header, linkt Server-Stub (Skeleton) IDL erlaubt unterschiedliche Sprachen für Client und Server
RPC-Ablauf mit Parameter Marshalling
Entwicklungsworkflow mit RPC und IDL
Call-by-value vs Call-by-reference Call-by-value Einfaches Marshalling Übertragen, ändern, zurücksenden, überschreiben Call-by-reference Ersetzt durch Call-by-copy/restore Sende Kopie des Objekts mit Eventuell rekursiv anwenden Reiner Input-Parameter: muss nicht zurückkopiert werden Reiner Output-Parameter: muss beim 1. Mal nicht hin- (nur zurückgeschickt werden)
Binding bei Client und Server Auffinden des RPC-Server durch einen Directory Server
Semantik von Aufrufen Fault tolerance measures Invocation semantics Retransmit request message Duplicate filtering Re-execute procedure or retransmit reply No Not applicable Not applicable Maybe Yes No Re-execute procedure At-least-once Yes Yes Retransmit reply At-most-once Idempotenz: Aufruf kann beliebig oft erfolgen gleiches Ergebnis Alle Remote Methods idempotent At least once ist ok
Distributed Objects RPC für Verteilung prozeduraler Sprachen wie C Moderner Ansatz: objekt-orientiert Remote method invocation (RMI) Objekte können Methoden von lokalen und remote Objekte gleichermassen aufrufen Keine Verteilung des internen Object State! Ziel: auf Sprachebene nicht unterscheidbar Ausnahme: Fehlerbehandlung (Exceptions)
RMI mittels Proxies
Parameterübergabe bei RMI Client A calls to Server C and passes local O1 by value and remote O2 by reference
Object Binding Client bzw. Server muss Objekt erst binden Bindung erzeugt Proxy wird im Addressraum des Clients Binding je nach System implizit oder explizit Nach Binding sieht RMI wie lokaler Methodenaufruf auf Distr_object* obj_ref; // Declare system-wide object reference obj_ref = ; // Initialize reference to distributed object obj_ref-> do_something(); // Implicitly bind and invoke a method Distr_object objpref; // Declare system-wide object reference Local_object* obj_ptr; // Declare pointer to local objects obj_ref = ; // Initialize reference to distributed object obj_ptr = bind(obj_ref); // Explicitly bind & obtain pointer to local proxy obj_ptr -> do_something(); // Invoke a method on the local proxy
Statisch Statisches vs dynamisches RMI Vordefinierte Interfaces (IDL oder Sprache) Änderung des Interface erfordert Neukompilierung objectname.methodname(in1, in2, out1, out2) Dynamisch Methodenaufruf zur Laufzeit generiert invoke(object, method, inparams, outparams) Erfordert Reflection für Lookup Methodenname Functionpointer Gestattet neue Klassen zur Laufzeit!
Erzeugung von Servants Factory Method (virtueller Konstruktor) Erzeugt gewünschte Objektinstanz indirekt Objekttyp = Parameter Speziell bei dynamischem RMI
Transient Objects Persistenz Existieren nur im Speicher des Server-Prozesses Können eventuell geswappt werden Persistent Objects Existieren unabhängig vom Server-Prozess Werden serialisiert auf externen Speicher abgelegt Eventuell serialisierte Snapshots nach jeder Invocation Transaction Rollback möglich Problem bei Inter-Objekt-Referenzen
Server Threads Mehrere Threads verringern Latenz bei gleichzeitigen RMIs Zugriffsschutz bei Aufrufen für dasselbe bzw. verknüpfte Objekte nötig
Distributed garbage collection Problem: Wann darf ein Servant Object gelöscht werden? Lösungsansatz: Reference Counting 1. Zugriff eines Clients (Binding) erhöht Counter Client erniedrigt Counter bei Proxy-Löschung Server löscht Servants mit Counter = 0
Probleme mit Reference Counting Verlorene Nachrichten Client Server: ref+1 Server Client: ACK...lost Client Server after timeout: retransmit re+1 Ergebnis: ref+2 Race conditions Client1 Server: ref+1 Client2 Server: ref-1...arrives before Client1 Server deletes ref, Client1 fails
Lösungsansätze Aufwendige Konsistenzprotokolle Bestätigung aller Prozesse, die Referenz haben, für jeden Vorgang nötig Reliable communication nötig Leases: Referenz nur begrenzte Zeit gültig Inkonsistenz kann nur zeitlich begrenzt sein Idempotente Nachrichten Server verwaltet Leases pro Client individuell Statt nur eines Reference Counters für alle Clients Keine Race Conditions möglich!
Java RMI In Sprache voll integriert Keine anderen Sprachen vorgesehen Interface Remote für Remote Objects Methodenaufrufe zwischen JVMs Marshalling durch Serialization IDL-Compiler rmic RMI-Daemon rmid Verwendet Sicherheitsmodell der Java Plattform Directory-Service rmiregistry (next slide)
The Naming class of Java RMIregistry void rebind (String name, Remote obj) This method is used by a server to register the identifier of a remote object by name, as shown in Figure 15.13, line 3. void bind (String name, Remote obj) This method can alternatively be used by a server to register a remote object by name, but if the name is already bound to a remote object reference an exception is thrown. void unbind (String name, Remote obj) This method removes a binding. Remote lookup (String name) This method is used by clients to look up a remote object by name, as shown in Figure 15.15 line 1. A remote object reference is returned. String [] list() This method returns an array of Strings containing the names bound in the registry.
Passing of Remote Objects Passing remote objects Parameter = remote interface always remote objects reference Use this reference to query the object by RMI Passing non remote objects Serializable copied and passed by-value Dynamic downloading of class code for unknown by-value object
Reflection in Java RMI Request messages enthält serialisiertes Method object Enhält class, argument types, exceptions Method.invoke kann auf Zielobjekt aufgerufen werden generisches Dispatching
Architektur von Java RMI S e r v e r - m a in M e t h o d e C lie n t - m a in M e t h o d e S e r v e r o b je k t S t u b / S k e le t o n S c h ic h t S t u b / S k e le t o n S c h ic h t R e m o t e R e f e r e n c e S c h ic h t / J V M R e m o t e R e f e r e n c e S c h ic h t / J V M K o m m u n ik a t io n s p r o t o k o ll ( I I O P ) P r o t o k o lls t a c k
Entwicklung für Java RMI C lie n t ( J a v a ) S c h n it t s t e lle ( J a v a ) S e r v e r ( J a v a ) ja v a c C lie n t S e r v e r C lie n t ( B y t e c o d e ) S c h n it t s t e lle ( B y t e c o d e ) S e r v e r ( B y t e c o d e ) r m ic C lie n t - S t u b ( B y t e c o d e ) S e r v e r - S t u b ( B y t e c o d e )
Distributed garbage collection in Java RMI Skeleton verwaltet Liste von Proxies Add/remove sind idempotent Reliable Communication nicht nötig Add Client erzeugt Reference Client sendet Reference id zu Server Client erzeugt Proxy erst nach Ack Vermeidung von Race Conditions Temporäre Referenz bevor/während Remote Reference übertragen wird Skaliert schlecht Verwendung von Leases
Beispiel: Collaborative Shape Drawing ShapeListClient - main() ShapeList proxy Shape proxy Interface - ShapeList - Shape ShapeListServer - main() ShapeListServant ShapeServant NameService ShapeList 1..N Clients greifen auf einen Shape Server zu
Java Remote interfaces Shape and ShapeList import java.rmi.*; import java.util.vector; public interface Shape extends Remote { int getversion() throws RemoteException; GraphicalObject getallstate() throws RemoteException; } public interface ShapeList extends Remote { Shape newshape(graphicalobject g) throws RemoteException; Vector allshapes() throws RemoteException; int getversion() throws RemoteException; }
Java class ShapeListServer with main method import java.rmi.*; public class ShapeListServer{ public static void main(string args[]){ System.setSecurityManager(new RMISecurityManager()); try{ ShapeList ashapelist = new ShapeListServant(); Naming.rebind("Shape List", ashapelist ); System.out.println("ShapeList server ready"); }catch(exception e) { System.out.println("ShapeList server main " + e.getmessage());} } }
ShapeListServant implements interface ShapeList import java.rmi.*; import java.rmi.server.unicastremoteobject; import java.util.vector; public class ShapeListServant extends UnicastRemoteObject implements ShapeList { private Vector thelist; // contains the list of Shapes 1 private int version; public ShapeListServant() throws RemoteException{...} public Shape newshape(graphicalobject g) throws RemoteException { 2 version++; Shape s = new ShapeServant( g, version); 3 thelist.addelement(s); return s; } public Vector allshapes()throws RemoteException{...} public int getversion() throws RemoteException {... } }
Java client of ShapeList import java.rmi.*; import java.rmi.server.*; import java.util.vector; public class ShapeListClient{ public static void main(string args[]){ System.setSecurityManager(new RMISecurityManager()); ShapeList ashapelist = null; try{ ashapelist = (ShapeList) Naming.lookup("//bruno.ShapeList"); 1 Vector slist = ashapelist.allshapes(); 2 } catch(remoteexception e) {System.out.println(e.getMessage()); } catch(exception e) {System.out.println("Client: " + e.getmessage());} } }
Events and Notifications Problem bei RPC/RMI: Information fliesst nur per Polling ( pull ) Verteilte Systeme benötigen oft Notifications über lokale Objekt-Änderungen (Events) Günstig zum Verbinden heterogener Systeme Point-to-point oder Multicast Realiable oder unreliable Notification
Observer Pattern Spezialisierungen für Observer Forwarding Filtering Pattern searching Mailbox
Publish-Subscribe Event charakterisiert durch Typ, Attribute Publisher gibt Arten von Events bekannt Subscriber abonniert bestimmte Events Publisher und Subscriber kennen sich nicht Referential Decoupling Art der Weiterleitung Direkt: Point to point, multicast Indirekt: Message Queue, Server-based Temporal decoupling Generelles Publish-Subscribe benötigt Broker
Publisher - Broker - Subscriber W a r t e s c h la n g e z u T h e m a a T h e m a a S u b s c r ib e r T h e m a b P u b lis h e r S u b s c r ib e r N a c h r ic h t b W a r t e s c h la n g e z u T h e m a b V e r m it t le r ( B r o k e r ) N a c h r ic h t b
Observer in Distributed Systems object of interest Event service subscriber 1. notification object of interest observer subscriber 2. notification notification object of interest observer subscriber 3. notification
Tuplespaces Asynchrones Publisher-Subscriber-System Tuplespace = temporäre Datenbank von Tuples Tuple = Nachricht mit geordneten Attributen Tuple(attrib1, attrib2, attrib3,..., attribn) Subscriber erhalten Daten durch Pattern Matching auf den Tupels GetTuple( Banana, *, *,..., 100) Funktionen: put, zerstörendes get Beispiel: JavaSpaces