Institut für Systemarchitektur Lehrstuhl Rechnernetze Praktikum Rechnernetze - Verteilte Systeme und Verteilte Anwendungen - Studienmaterial -1- Vorwort Die große Bedeutung Verteilter Anwendungen bedarf in der heutigen, vernetzten Welt kaum noch der Erwähnung. Zu sehr haben sie Einzug in alle Lebens- und Wirkensbereiche des Menschen gefunden, als dass in der Gesellschaft über einen Verzicht der mit ihr verbundenen Kommunikations- und Organisationserleichterungen bzw. sozialen Bedeutungen nachgedacht werden könnte. Diese Abhandlung befasst sich in ihrem ersten Abschnitt mit grundlegenden Konzepten verteilter Anwendungen. Der dabei auftretenden, scheinbaren Komplexität dieses Themenfeldes soll durch die Behandlung weniger, aber dafür wichtiger Teilbereiche entgegen gewirkt werden. Durch diese wird in entscheidende Begriffe und in das konzeptionelle Grundverständnis eingeführt, die bei der Bearbeitung der Versuche des Praktikums bzw. Komplexpraktikums Rechnernetze und bei weiteren Arbeiten in diesem Bereich hilfreich sind. Zudem soll dadurch eine gemeinsame Wissensbasis aller Praktikumsteilnehmer geschaffen werden. Besonderer Wert wird in diesem Zusammenhang neben Kommunikations- und Architekturprinzipien innerhalb verteilter Anwendungen auf maßgebliche Eigenschaften und Formen von Middleware gelegt. Im zweiten Abschnitt sind daraufhin die im Praktikum behandelten Technologien in einen Gesamtzusammenhang gebracht und einzelne technologische Aspekte vergleichend gegenüber gestellt. Dazu wird auf die Bedeutung von Java RMI eingegangen, die heutige Rolle von CORBA dargestellt, der Zusammenhang von COM+ und .NET aufgezeigt und schließlich die wirtschaftlich relevantesten Plattformen, J2EE und .NET, in entscheidenden Zügen auf Gemeinsamkeiten und Unterschiede untersucht. -2- Vorwort ................................................................................................................................. - 2 Teil I ....................................................................................................................................... - 5 1 2 Einführung .................................................................................................................... - 5 1.1 Verteilte Systeme .................................................................................................. - 5 - 1.2 Verteilte Anwendungen ....................................................................................... - 6 - Grundlegende Konzepte .............................................................................................. - 9 2.1 2.1.1 Nachrichten .................................................................................................... - 9 - 2.1.2 Entfernte Prozeduraufrufe ............................................................................ - 10 - 2.1.3 Entfernte Objektkommunikation .................................................................. - 13 - 2.1.4 Komponenten ............................................................................................... - 16 - 2.2 Middleware ......................................................................................................... - 17 - 2.3 Dienste ................................................................................................................. - 18 - 2.3.1 Namensdienste ............................................................................................. - 18 - 2.3.2 Transaktionsdienste ...................................................................................... - 20 - 2.3.3 Sicherheitsdienste ......................................................................................... - 21 - 2.4 3 Kommunikationskonzepte und Programmierparadigmen .............................. - 9 - Architekturprinzipien ........................................................................................ - 22 - 2.4.1 2-Schichten Architektur ............................................................................... - 22 - 2.4.2 3-Schichten Architektur ............................................................................... - 23 - 2.4.3 n-Schichten Architektur ............................................................................... - 23 - 2.4.4 Clients........................................................................................................... - 24 - Beispiele: Ausprägungen verteilter Systeme............................................................ - 25 3.1 Webanwendungen .............................................................................................. - 25 - 3.2 Webservices......................................................................................................... - 25 - 3.2.1 XML ............................................................................................................. - 26 - 3.2.2 WSDL........................................................................................................... - 27 - 3.2.3 SOAP ............................................................................................................ - 28 - 3.2.4 UDDI ............................................................................................................ - 28 - 3.2.5 Ablauf einer Webservice-Kommunikation .................................................. - 29 - Teil II ................................................................................................................................... - 30 4 Grundlegendes ............................................................................................................ - 30 - 5 Corba und Java-RMI ................................................................................................. - 30 5.1 Unterschiede ....................................................................................................... - 30 - 5.2 Gemeinsamkeit ................................................................................................... - 31 - -3- 6 Von COM zu .NET ..................................................................................................... - 32 6.1 Schwächen von COM+ ...................................................................................... - 32 - 6.2 Interoperabilität zwischen COM und .NET .................................................... - 33 - 7 .NET im Vergleich zu J2EE ...................................................................................... - 34 - 8 Anhang ........................................................................................................................ - 36 8.1 Abbildungsverzeichnis ....................................................................................... - 36 - 8.2 Tabellenverzeichnis ............................................................................................ - 36 - 8.3 Abkürzungsverzeichnis ...................................................................................... - 37 - 8.4 Literatur .............................................................................................................. - 38 - -4- Teil I 1 Einführung Verteilte Anwendungen und Verteilte Systeme erscheinen heute in unterschiedlichsten Ausprägungen und Facetten, angefangen bei klassischer Verteilung auf Ebene von Großrechnern, bis hin zur Verteilung auf Ebene von mobilen oder eingebetteten Systemen. Die Begriffe sind im Sprachgebrauch des auf Anwendungsentwicklung ausgerichteten Informatikers fest verankert. Doch was zeichnet ein verteiltes System in seinen Eigenschaften aus und wie grenzt sich ihm gegenüber eine verteilte Anwendung ab? 1.1 Verteilte Systeme Grundlage für ein Verteiltes System bildet ein vernetztes Geflecht von Rechnerknoten, auf denen einzelne Elemente einer Anwendung räumlich getrennt ausgeführt werden. Um ein Verteiltes System handelt es sich, falls auf dieser Basis ein Softwaresystem aufsetzt, das die zunächst noch getrennte Verarbeitung durch ein Angebot verschiedener KommunikationsMechanismen, wie etwa transportorientierter Protokolle, zu einem Gesamtsystem verschmelzen lässt. Nach [1] unterscheidet sich ein Verteiltes System von einem Rechnernetz durch die Tatsache, dass der Nutzer die zunächst „unabhängigen Computer als ein einheitliches kohärentes System“ (S.16) wahrnimmt. Dies wird allein durch die Softwareebene erzielt. Das wohl bekannteste Verteilte System ist das Internet, in dem Millionen von Rechnern über Protokolle der TCP/IP-Familie miteinander kommunizieren. Wird ein Verteiltes System als Lösung für ein Anwendungsproblem eingesetzt, spricht man damit von Verteilter Verarbeitung. Beim Gedanken an ein großes Rechnernetz stößt man schnell auf einige typische Probleme, die bei der Kopplung entstehen. Dazu gehören insbesondere folgende: Heterogenität des Rechnernetzes Möglichkeit des Rechnerausfalls Fehleranfälligkeit der Kommunikation Hoher Administrationsaufwand Komplexität der Hardware-Infrastruktur Neben diesen allgemeinen Punkten existieren zahlreiche weitere Probleme, wie das Fehlen eines gemeinsamen Zustandes und ein Nichtdeterminismus von Nachrichtenlaufzeiten, die sich beispielsweise auf die Komplexität des Debugging auswirken. Ein ausgefeiltes Verteiltes System zielt auf die Überwindung dieser Probleme, vor allem der technischen Heterogenität durch vereinheitlichte Kommunikationsmechanismen, ab und bietet -5- dabei einen hohen Grad an nebenläufiger Verarbeitung und Transparenz. Unter Transparenz ist dabei das Verbergen von Aspekten der Verteilung, wie beispielsweise Kommunikationsdetails, zu verstehen. Sie wird sowohl von Anwendern, als auch von Entwicklern gefordert. Konkret werden darunter beispielsweise folgende Formen verstanden: 1.2 Ortstransparenz Der physikalische Standort einer genutzten Ressource bleibt verborgen. Zugriffstransparenz Der Zugriff auf lokal vorliegende Ressourcen und entfernte Ressourcen ist syntaktisch gleich. Implementationstransparenz Von technischen Details wird bei der Anwendungsentwicklung auf einem Verteilten System abstrahiert. Ausfalltransparenz Ein temporärer oder dauerhafter Ausfall eines Teilbereichs des Verteilten Systems bleibt dem Nutzer verborgen. Verteilte Anwendungen Ebenso wie ein Rechnernetz die Grundlage für ein Verteiltes System bildet, so bildet ein Verteiltes System wiederum die Grundlage für eine Verteilte Anwendung. Dieser Zusammenhang ist in Abbildung 1 dargestellt. Anwendungsbestandteil Verteilte Anwendung Rechner Anwendungsbestandteil Rechner Verteiles System Netzwerkverbindung Abbildung 1: Einordnung Verteilter Anwendungen Eine Verteilte Anwendung stellt eine eigenständige, geschlossene logische Einheit dar, die aus mehreren auf verschiedenen Rechnerknoten verteilte Funktionseinheiten besteht. Erst durch die Kooperation der Einzelbestandteile der Anwendung erfüllt sie eine komplexere Aufgabe. Beispiele sind zum einen einfache Verteilte Anwendungen, wie das WWW oder EMailsysteme, bestehend aus Client- und Serverprogrammen. Erst durch die Existenz der -6- beiden definierten Rollen des Dienstanbieters und Dienstnutzers bzw. durch die Kommunikation zwischen ihnen entsteht so eine Verteilte Anwendung. Zum anderen kann es sich aber auch um wesentlich komplexere Systeme handeln, wie beispielsweise Verteilte Informationssysteme, die etwa organisatorische Prozesse eines Unternehmens unterstützen. Maßgebliches Klassifikationskriterium dieser Informationssysteme sind eine starke Datenzentrierung und ein komfortabler Zugriff auf die verwalteten Daten. Gegenüber herkömmlichen, monolithischen Anwendungen zeichnet eine Verteilte Anwendung einige große Vorteile aus: Verteilung von Daten, Funktionen und Last Dezentralisierung und Kooperation Effizienz durch parallele Verarbeitung Gemeinsame Nutzung von Ressourcen Integration bestehender Systeme durch Kommunikationsschnittstellen Fehlertoleranz, Ausfallsicherheit und Verfügbarkeit Neben diesen Vorteilen ergeben sich intuitiv zahlreiche weitere Argumente für die Verteilung, zumal zahlreiche Anwendungen ohne den Aspekt der Dezentralisierung undenkbar sind. Die folgende Abbildung 2 zeigt ein typisches Szenario für eine Verteilte Anwendung, bei der zwei verschiedene Kategorien von Clients die Dienste einer Fluggesellschaft in Anspruch nehmen können. Reisebüro Fluggesellschaft Clientprogramm Webserver Internet Buchungsserver Kunde Datenbankserver Webbrowser Abbildung 2: Beispiel einer Verteilten Anwendung Mit der Bedeutung von Verteilten Anwendungen haben ebenso die Anforderungen an sie deutlich zugenommen. Ging es zunächst nur um den Austausch von Informationen über Rechnergrenzen hinweg, so gelten heute gleich eine Reihe von geradezu Selbstverständlichkeiten für neu entwickelte Verteilte Anwendungen. -7- Dazu gehören unter anderem: Verfügbarkeit Skalierbarkeit Integration anderer, insbesondere älterer Anwendungen Kurze Entwicklungszyklen Mehrbenutzerfähigkeit Leichte Konfigurierbarkeit Effiziente Kommunikation Sicherheit Da es sich innerhalb der Softwareentwicklung bei einigen dieser Anforderungen um immer wiederkehrende Aspekte handelt, liegt es nahe, sie nicht für jede Anwendung neu umzusetzen, sondern in Form umfangreicher Dienste und Werkzeuge zur Verfügung zu stellen, die leicht in eigene Anwendungen integriert werden können. Neben der Realisierungsmöglichkeit einer solchen Systemunterstützung wird im nächsten Absatz detailliert auf grundlegende Konzepte verteilter Anwendungen eingegangen. -8- 2 Grundlegende Konzepte Nachdem nun die beiden Begriffe „Verteiltes System“ und „Verteilte Anwendung“ voneinander abgegrenzt wurden, wird in der Folge weiter ins Detail der Verteilung vorgedrungen. Als Grundlage dazu dienen folgende drei Fragen: 2.1 Wie läuft die Kommunikation konzeptionell zwischen den beteiligten Einheiten ab? Welche Dienste benötigt eine Verteilte Anwendung und wie können diese ihr möglichst einfach zugänglich gemacht werden? Nach welchen Architekturprinzipien können Verteilte Anwendungen gestaltet werden? Kommunikationskonzepte und Programmierparadigmen Die Basis für ein Verteiltes System und damit auch für eine Verteilte Anwendung stellt selbstverständlich die Kommunikation zwischen den beteiligten Elementen dar. Die Kommunikation kann dabei nach unterschiedlichen Mechanismen aufbauend auf verschiedenen Bearbeitungs- und Programmierparadigmen ablaufen. Die Entwicklung der in der Folge dargestellten Kommunikationsmodelle ist dabei in historischer Analogie zu den Anforderungen an die Softwareentwicklung im Allgemeinen zu sehen. So erfolgte beispielsweise die Entwicklung von Objektorientierten Kommunikationsansätzen zeitgleich mit dem Erstarken der Objektorientierung. 2.1.1 Nachrichten Die erste und einfachste Form von Informationsaustausch zur Realisierung einer verteilten Verarbeitung stellen Nachrichtenbasierte Systeme dar. Sie arbeiten für gewöhnlich nach dem Prinzip von Warteschlangen (Message Queues), bei dem ein Sender die Möglichkeit hat, durch Systemaufrufe Daten in einen speziellen Puffer (Output Queue) abzulegen, die von dort aus zu bestimmten Zeitpunkten versendet werden. Initiiert werden kann der Versandvorgang dabei entweder von der jeweiligen Anwendung selbst oder aber etwa vom Betriebssystem. Ebenso existieren Implementierungen, bei denen jede Anwendung eine eigene Warteschlange besitzt und solche, bei denen systemweite Warteschlangen vorliegen, auf die mit entsprechenden Synchronisationsmechanismen zugegriffen wird. Der Eingang von Nachrichten verläuft analog zum Nachrichtenausgang. Auch hier wird der empfangenden Anwendung eine Warteschlange (Input Queue) vorgeschaltet, in die Nachrichten zunächst abgelegt werden. Durch eine eingehende Nachricht kann daraufhin beispielsweise ein Interrupt ausgelöst werden oder die Applikation prüft in regelmäßigen Abständen selbst, ob Nachrichten empfangen wurden. Abbildung 3 zeigt zwei über Warteschlangen kommunizierende Anwendungen, denen jeweils ein Eingangs- und Ausgangspuffer zugeordnet ist. -9- Anwendung 1 Anwendung 2 receive() Input-Queue Output-Queue send() send() Output-Queue Input-Queue receive() Abbildung 3: Kommunikation über Nachrichten Auch wenn dieser Ansatz bereits lange existiert und insbesondere aufgrund unterschiedlichster konkreter Implementierungen keinen Standard bildet, so findet er doch nach wie vor Verwendung. Vor allem der Aspekt der Asynchronität und der Entkopplung von Sender und Empfänger macht ihn auch für aktuelle Technologien interessant. Man denke dazu beispielsweise an mobile Kommunikation innerhalb hoch dynamischer Infrastrukturen. Dabei können Nachrichten bei fehlender Netzanbindung des Kommunikationsgeräts von einer Anwendung zunächst in die entsprechende Warteschlange abgelegt und, sobald wieder eine Netzanbindung vorliegt, an den Kommunikationspartner ausgeliefert werden. 2.1.2 Entfernte Prozeduraufrufe Bei einem entfernten Prozeduraufruf (Remote Procedure Call, RPC) handelt es sich um ein Netzwerkprotokoll, das den Aufruf von Prozeduren auf anderen Rechnern über ein Netzwerk ermöglicht. Ursprünglich wurde er entwickelt, um auf entfernte Dateien zugreifen zu können, dann aber auf beliebige Aufrufe erweitert. Grundlage dieses Ansatzes bildet das klassische Client-/Server-Modell, bei dem ein ClientProgramm mit entsprechenden Systemaufrufen einen RPC-Server ansprechen kann. Der Client gibt dabei an, welche Funktion mit welchen Parametern aufgerufen werden soll. Die Parameter werden als Wertparameter übermittelt. Der genaue Ablauf einer klassischen RPCKommunikation ist in Abbildung 4 dargestellt. - 10 - 1. Absetzen des Aufrufs 2. Kodierung des Aufrufs 3. Warten 5. Dekodierung 6. Ausführung 7. Kodierung 8. Dekodierung 9. Erhalt der Ergebnisse 10. Fortsetzung des Programms Abbildung 4: Ablauf einer Kommunikation mittels RPC (aus [2]) Zu sehen ist hierbei insbesondere, dass die Übergabe des Kontrollflusses synchron erfolgt. Der Client-Prozess blockiert nach Absetzen des Aufrufs so lange, bis ein Ergebnis eingetroffen ist und die Abarbeitung des Programms weitergeführt werden kann. Ziel beim Protokollentwurf war allen voran eine möglichst große Transparenz für den Client. Ein entfernter Prozeduraufruf soll also möglichst stark einem lokalen Aufruf ähneln, wenn nicht sogar identisch sein. Ermöglicht wird diese Transparenz durch das StellvertreterKonzept. Anstelle der tatsächlichen Prozedur verfügt der Client nur über einen Stellvertreter (Stub), der das Verhalten der entfernten Prozedur simuliert, also die gleiche Signatur besitzt. Beim Aufruf sorgt der Stub nun vollkommen transparent für die Umwandlung der Parameter in ein übertragbares Format (Marshalling) und für das Absetzen des Aufrufs an den Server. Auf Serverseite nimmt entsprechend ein Server-Stub die Anfrage entgegen und sorgt für die Dekodierung der Anfrage samt ihrer Parameter (Unmarshalling). Nach Ausführung der jeweiligen Prozedur auf Serverseite erfolgt die Ergebnisrückgabe auf analogem Wege. Damit ein Entwickler sich nicht um die Details der Stub-Programmierung kümmern muss und damit ein Stub gewissen Standards entspricht, können die Stellvertreter für Client und Server automatisch mit entsprechenden Werkzeugen aus den Prozedurschnittstellen generiert werden. Diese Schnittstellen werden dazu in einer Schnittstellenbeschreibungssprache (Interface Definition Language - IDL) definiert. In der IDL werden Angaben über Datentypen, Prozedurnamen, Parameter und Rückgabewerte der Prozeduren gemacht. Zusätzlich weisen die Beschreibungen eine systemweit eindeutige Schnittstellenkennung (UUID) und eine Versionsangabe neben potentiell weiteren Informationen auf. Der Weg von einer IDL-Datei mit Hilfe eines IDL-Compilers zum Client- und Server-Stub, die dann in entsprechende Programme eingebunden werden können, ist in Abbildung 5 an einem Beispiel dargestellt. - 11 - document.idl IDL-Compiler document_cstub.o document.h document_sstub.o #include document_client.c document_server.c C compile document_client.o document_server.o link link document_client.exe document_server.exe Abbildung 5: Stub-Generierung aus IDL-Datei (aus [2]) Ein entscheidender Aspekt wurde bis jetzt ausgeblendet: Woher weiß ein Client welcher Server über eine bestimmten Prozedur verfügt? Möglich wäre natürlich eine direkte Bekanntgabe einer Serveradresse im Quellcode (Direktadressierung) oder das Absetzen eines Broadcasts im Netz. Insbesondere in anonymen und großen Netzen haben beide Ansätze zahlreiche Nachteile. Eine geeignete Lösung bietet der Einsatz eines Directory-Services, der Informationen darüber speichert, welcher Server welche Prozedur in welcher Version etc. zur Verfügung stellt. Der Einsatz eines Directory-Dienstes ist in Abbildung 6 dargestellt: - 12 - Directory-Server Datenbestand 2 1 Client Server Bindevorgang 3 call_remote() implementation() Abbildung 6: Directory-Service im RPC-System 1. Ein RPC-Server muss die Beschreibungen der Schnittstellen angebotener Prozeduren samt seiner Adresse an den Directory-Server propagieren. Dieser Vorgang wird als Export von Bindeinformationen bezeichnet. 2. Der Client stellt an den Directory-Server eine Anfrage, welcher Server eine bestimmte Prozedur anbietet und bekommt eine Serveradresse zurück geliefert (Import). 3. Damit ist der Client in der Lage, den ermittelten Server an sich zu binden und die entfernte Prozedur aufzurufen. Alternativ zur Vorgabe eines einzigen Servers kann dem Client auch eine Liste möglicher Diensterbringer übergeben werden, von dem er sich den Besten, im Sinne von z.B. am geringsten belastet, aussucht. In der Praxis gibt es zahlreiche Implementierung des RPC-Modells, wie etwa den Sun-RPC, den DCE-RPC oder den etwas neueren XML-RPC. Zudem wurde das beschriebene, klassische Konzept dabei häufig aufgelöst, um ein flexibleres System zu schaffen. Zu Kritikpunkten am klassischen RPC und möglichen Verbesserungen siehe [2]. 2.1.3 Entfernte Objektkommunikation Entfernte Prozeduraufrufe stammen aus einer Zeit, in der Unix und prozedurale Programmiersprachen häufigste Grundlage für Verteilte Anwendungen bildeten. Mit dem Erstarken des Konzepts Objektorientierter Programmierung entwickelte sich der Wunsch, analog zum entfernten Prozeduraufruf mit entfernten Objekten interagieren zu können. Diese Möglichkeit wurde mit dem Prinzip der Remote Method Invocation (RMI) eingeführt. Der konzeptionelle Ablauf ist dabei dem des RPC sehr ähnlich. Die theoretischen Grundlagen einer entfernten Objektkommunikation werden dazu im - 13 - Praktikum am Beispiel von Java-RMI behandelt und sollen an dieser Stelle nicht weiter diskutiert werden. Die folgende tabellarische Übersicht vergleicht die Ansätze des entfernter Prozeduraufrufs im Client-/Server-Modell und des entfernten Methodenaufrufs. Client-/Server-Modell Verteiltes objektorientiertes Modell Verarbeitungsmodell Prozedurales Modell mit Objektkommunikation Einschränkungen Zugriffsweise auf Daten Datenzugriff indirekt über RPC-Server Direktzugriff auf Objekte Datenübergabe Wertparameter-Semantik ReferenzparameterSemantik Identität Nicht systemweit eindeutig Systemweit eindeutig Granularität Server grober Granularität Objekte beliebiger Granularität Platzierung Feste Platzierung Modifizierbare Platzierung Tabelle 1: Vergleich des Client-/Server- und Objektorientiertem Modell (aus [2]) An die Tatsache, dass die Platzierung der Objekte innerhalb einer Verteilten Anwendung beliebig sein soll, schließt sich die Notwendigkeit der Objektmigration, also die dynamische Verlagerung von Objekten innerhalb des Systems, an. Die Objektmigration wird aufgrund folgender Überlegungen befürwortet: Bietet Möglichkeit Objekte von stark auf schwach belastete Server zu verlagern Client kann ein Objekt anfordern und lokal darauf operieren Nachbildung von natürlichen Abläufen, z.B. von Büroabläufen, wird erleichtert Hoher Grad an Verteilungstransparenz Um bei der Objektmigration einen transparenten Zugriff auf das Objekt nach wie vor zu gewährleisten, wird das Objekt durch einen Stellvertreter (Proxy-Objekt) ersetzt, der alle Anfragen an das migrierte Objekt weiterleitet. Dieses Prinzip ist in Abbildung 7 dargestellt. - 14 - Rechner 1 Rechner 2 Rechner 3 P2 O1 O3 O2 P3 P4 O4 Ox Px Objekt x Proxy-Objekt für Objekt x Abbildung 7: Stellvertreter bei migrierten Objekten Ein Problem bildet bei nicht fest an einen Ort gebundenen Objekten die Aktualisierung des Stellvertreters, damit dieser auf die neue Adresse verweist. Maßgeblich existieren drei Möglichkeiten eine Lokalisierung von migrierten Objekten zu gewährleisten: 1. Betrieb eines zentralen Verzeichnisdienstes, der immer über den aktuellen Ort aller Objekte im System informiert wird. Vorteil: einfach zu realisieren Nachteil: unflexibel, Ausfallgefahr 2. Sofort bei Migration werden alle Stellvertreter über die neue Lokation informiert. Vorteil: bei späteren Aufrufen wird Objekt mit geringem Aufwand erreicht Nachteil: geringe Skalierbarkeit, hoher Migrationsaufwand 3. Auf dem Rechner, auf dem sich das Objekt vor der Migration befand wird ein weiterer Stellvertreter installiert, so dass sich Ketten von Stellvertreten bilden, durch die Anfragen weitergereicht werden. Vorteil: geringer Migrationsaufwand, flexibel Nachteil: lange Verweisketten Ein weiterer wichtiger Themenbereich in diesem Zusammenhang ist die verteilte GarbageCollection, also die Beseitigung nicht mehr benötigter Objekte. Die im Falle Java-RMI ablaufenden Vorgänge sind unter [9] beschrieben. Die verteilte Objektorientierte Kommunikation findet heute insbesondere aufgrund eines sehr intuitiven Modells und großer Flexibilität in zahlreichen Verteilten Anwendungen Einsatz. Zudem bilden konkrete Ausprägungen, wie Java-RMI die Grundlage für Teilanwendungen in komplexeren Kontexten, wie etwa das Beispiel JNDI zeigt. Siehe dazu auch den zweiten Teil dieser Abhandlung. - 15 - 2.1.4 Komponenten Durch die zahlreich abzudeckenden Aufgaben, wie etwa die Datenhaltung, die Implementierung der Logik, die Kommunikation zwischen verteilter Logik und dergleichen, sind Verteilte Anwendungen in der Vergangenheit schnell sehr komplex und umfangreich geworden. Besonders in Kombination mit schlechter Strukturierung des Quellcodes führte dies zu nahezu unwartbaren Programmen, die bei kleinen Änderungen fast vollständig neu geschrieben werden mussten. Die klassischen Programmierparadigmen konnten für das Problem inhaltlicher und technischer Abhängigkeiten in diesem Code keinen Ausweg bieten. Die Objektorientierung verbesserte zwar die Plan- und Strukturierbarkeit, doch auch hier sind in der Praxis starke Interdependenzen in den Quelltexten zu verzeichnen. Somit wurde das Konzept der Komponenten entworfen, bei denen es sich prinzipiell um kleine Software-Bausteine in binärer Form handelt, die Daten und Funktionen kapseln und nur über genau definierte Schnittstellen von außen zugänglich sind. Dadurch werden Abhängigkeiten in einer Anwendung beherrschbar gemacht. Die Logik innerhalb einer Komponente kann bei gleich bleibender Schnittstelle ausgetauscht werden, ohne andere Bereiche der Anwendung zu verändern. Durch die Eigenschaft der Softwarekomponenten, in sich geschlossene Einheiten zu sein, können sie getrennt von einander entwickelt, übersetzt und vertrieben werden. Sie bilden eine Blackbox, deren Logik nicht nach außen bekannt sein muss. Für die Erstellung einer großen Anwendung reicht es zu wissen, was eine Komponente kann und wie über ihre Schnittstellen mit ihr kommuniziert wird. Die genannte Definition bildet den kleinsten gemeinsamen Nenner der in der Literatur und in konkreten Technologien häufig sehr unterschiedlichen Definitionen des Komponentenbegriffs. Beispiele für konkrete Komponententechnologien sind das Distributed Component Object Model (DCOM), Enterprise Java Beans (EJBs) und das CORBA Component Model, die alle drei für die Entwicklung Verteilter Anwendungen geschaffen wurden. Die Kommunikation läuft dabei häufig mit weit verbreiteten Protokollen ab, wie etwa dem Internet Inter ORB Protocol oder dem Java-RMI-Protokoll. Auch daran wird ein zentraler Punkt innerhalb der Komponentenmodelle deutlich: Sie bilden nicht etwa ein vollkommen neues Konzept, sondern setzen auf alten Konzepten wie der Objektorientierung auf und fügen diesen das Element der Strukturierung durch Kapselung und standardisierten Zugriff hinzu. Neben regulären Komponenten bilden eingebettete Komponenten eine spezielle Form. Diese benötigen eine als Container bezeichnete Laufzeitumgebung, die ihnen Dienste wie Namensoder Sicherheitsdienste zur Verfügung stellt. Eine Form einer solchen Umgebung ist der Applicationserver. Abbildung 8 zeigt die Interaktion eines Clients mit Komponenten innerhalb eines Containers am Beispiel der Enterprise Java Beans. - 16 - J2EE-Applicationserver create() lookup() methodX() … Web-Container EJB-Container Naming Service EJB-Object Client EJB-Factory SessionBean Security EntityBean … Abbildung 8: Enterprise Java Beans im Kontext eines Applicationservers 2.2 Middleware Grundlegende Möglichkeiten zur Kommunikation werden einer Verteilten Anwendung bereits vom zugrunde liegenden Verteilten System angeboten. Dieses stellt allerdings hauptsächlich rudimentäre Funktionalitäten zur Verfügung, wie Verbindungsverwaltung oder Fehlerbehandlung bei der Übertragung, die zwar selbst von der Byteübertragung etc. abstrahieren, dennoch aber auf einer logisch niedrigen Ebene genutzt werden. Etwa bei der Socket-Kommunikation setzt eine Verteilte Anwendung unmittelbar auf einem Verteilten System auf, was als Netzwerkprogrammierung bezeichnet wird. Von den dabei durchzuführenden Arbeiten soll durch eine Middleware abstrahiert werden. Dabei handelt es sich um eine zusätzliche Softwareschicht, die selbst auf das ursprüngliche Verteilte System zugreift und Verteilten Anwendungen bestimmte Dienstleistungen anbietet. Die Struktur ist in Abbildung 9 dargestellt. Verteilte Anwendung Dienste Verteilte Anwendung Dienste Verteilte Anwendung Dienste Middleware Verteiltes System Abbildung 9: Einordnung von Middleware - 17 - Dienste Durch dieses Prinzip operiert eine Verteilte Anwendung auf einer logisch höheren Ebene und verwendet die durch die Middleware verfügbaren Funktionalitäten. Die Dienste sind über definierte Schnittstellen zugänglich. Je nach angebotenen Dienstleistungen wird Middleware unterteilt in: 2.3 Kommunikationsorientierte Middleware Hauptaufgabe ist die Abstraktion von der Netzwerkprogrammierung. Dazu bietet sie ein eigenes Protokoll an, das zur Kommunikation innerhalb der Anwendung verwendet werden kann. So handelt es sich bei Java-RMI beispielsweise um eine kommunikationsorientierte Middleware. Anwendungsorientierte Middleware Neben dem Aspekt der Abstraktion von der Netzwerkprogrammierung bietet diese Form von Middleware einer Verteilten Anwendung zusätzliche Laufzeitfunktionalitäten bzw. Dienste an. CORBA und .NET sind typische anwendungsorientierte Middleware-Plattformen. Dienste Das Konzept des Dienstes, der innerhalb einer Middleware von einer Anwendung genutzt werden kann, hat den offensichtlichen Vorteil der Widerverwendbarkeit von Funktionalität. Doch welche Funktionalitäten werden von zahlreichen Anwendungen benötigt und sind damit prädestiniert, zentral angeboten zu werden? In der Folge sind drei Dienste in den Grundzügen erläutert. Daneben gibt es zahlreiche weitere Dienste, wie Sitzungs- oder Persistenzdienste. 2.3.1 Namensdienste Bereits bei der Darstellung des RPC wurde kurz der Namensdienst in Form eines Directory Services erwähnt. Mit Hilfe von Namensdiensten können Ressourcen innerhalb eines Netzes aufgefunden werden. Bei einer Ressource kann es sich beispielsweise um einen anderen Rechner, um eine konkrete Funktionalität, ein Objekt oder eine Referenz auf ein Objekt handeln. Es erfolgt dazu eine Zuordnung der physikalischen Adresse einer Ressource zu einem logischen Namen. Die Verknüpfung eines Namens mit einer Ressource wird auch als Binding bezeichnet. Zur Ermittlung einer Ressource übergibt ein Client den logischen Namen an den Dienst und erhält die gewünschte Adresse. In einem größeren Netz mit zahlreichen Anwendungsfällen für einen Namensdienst sind die von ihm verwalteten Informationen schnell recht umfangreich. Eine einfache tabellarische Organisation der Bindings reicht in der Regel nicht aus. Daher werden die Daten häufig in baumartigen Strukturen verwaltet. Die Blätter bilden dabei die Ressourcen, die Knoten werden als Kontexte bezeichnet. Ein Kontext ist damit also eine Menge von Bindings. Diese hierarchische Struktur ist in Abbildung 10 dargestellt. - 18 - Kontext Objekt ObjektReferenz Abbildung 10: Namensorganisation (nach [8], S.25) Die hier aufgezeigte Struktur wird in gleicher Form etwa vom J2EE-Namensdienst, dem Java Naming and Directory Interface (JNDI) verwendet. Neben der effizienteren Abfrage von Informationen innerhalb der baumartigen Struktur ergibt sich ein weiterer Vorteil. Die Kontexte sind auf verschiedene Rechner verteilbar, wie es im Falle des Domain Name Systems, des Namensdienstes im Internet geschieht. Für eine Anfrage nach einer im Gesamtsystem vorhandenen Adresse auf eine Ressource gibt es dann drei Möglichkeiten: 1. Der Server kann die Anfrage innerhalb seines Kontextes beantworten. 2. Der Server besitzt einen Verweis auf einen anderen Server, der den Kontext zur Beantwortung der Anfrage verwaltet. 3. Falls 1. und 2. nicht zutrifft, so reicht der Server die Anfrage an einen Server einer höheren Hierarchiestufe weiter. Die Aufteilung der Kontexte auf unterschiedliche Rechner ist in Abbildung 11 dargestellt. Nameserver S1: Kontext „Firmennamen“ Nameserver S2: Kontext „Abteilung_Firma_A“ Nameserver S4: Kontext „Entwicklung_Firma_A“ Nameserver S3: Kontext „Abteilung_Firma_B“ Nameserver S5: Kontext „Fertigung_Firma_A“ Nameserver S6: Kontext „Fertigung_Firma_B“ Abbildung 11: Verteilung der Kontexte auf unterschiedliche Server (aus [2]) - 19 - Ein Kontext wird in größeren Netzen nicht ausschließlich von einem einzelnen Server verwaltet, sondern liegt repliziert auf mehreren Rechnern vor, was der Ausfallsicherheit des Gesamtsystems entgegen wirkt. Ein „Single Point of Failure“ wird so vermieden. 2.3.2 Transaktionsdienste Innerhalb einer datenzentrierten Verteilten Anwendung müssen die verwalteten Daten konsistent sein, das bedeutet sie müssen einen gültigen Zustand repräsentieren. Bei parallelen Zugriffen auf die Datenbasis von mehreren Anwendungsbestandteilen aus ist diese Konsistenz gefährdet, falls dabei mehrere Instanzen Daten gleichzeitig ändern wollen. Ebenso stellt die Kommunikation über das Netzwerk oder die Aufteilung der Datenbestände auf mehrere Rechner eine Gefahr für die Konsistenz dar. Damit die Konsistenz erhalten bleibt, werden vier Forderungen für den Zugriff auf die Datenbasis aufgestellt: 1. Atomizität Eine Aktion wird entweder vollständig oder gar nicht ausgeführt. 2. Konsistenz (engl. Consistency) Ein konsistenter Zustand wird immer in einen konsistenten Zustand überführt. 3. Isolation Zugriffe auf die Datenbasis stören sich nicht gegenseitig. 4. Dauerhaftigkeit Einmal festgeschriebene Daten sind dauerhaft festgeschrieben. Ein Vorgang, der diese als ACID-Prinzip bekannten Forderungen erfüllt, wird als Transaktion bezeichnet, eine Transaktion innerhalb einer verteilten Anwendung heißt entsprechend verteilte Transaktion. Ein weit verbreitetes Transaktionsprotokoll ist das 2-Phasen-Commit-Protokoll. Dieses ist in Abbildung 12 an einem Beispiel dargestellt. Ein Koordinator, z.B. ein Client-Programm will dabei Daten auf drei Teilnehmern, z.B. Datenbankservern konsistent abspeichern. 1 Teilnehmer 1 2 3 Koordinator Teilnehmer 2 Teilnehmer 3 Abbildung 12: Ablauf des 2-Phasen-Commit-Protokolls - 20 - Der Ablauf ist folgender: 1. Der Koordinator schickt den Teilnehmern eine „prepare“-Nachricht, die dadurch veranlasst werden, zu überprüfen, ob die Daten persistent gemacht werden können. 2. Ist das der Fall schicken sie eine Bestätigung, ansonsten eine Abbruch-Meldung. 3. Im Falle der positiven Bestätigung durch die Teilnehmer schickt der Koordinator den Teilnehmern eine „commit“-Nachricht, die sie veranlasst die Änderungen aus 1. dauerhaft zu machen. Bei einer negativen Antwort eines Teilnehmers im Schritt 2. schickt der Koordinator eine „rollback“-Nachricht, durch die die Teilnehmer die Änderung verwerfen. Für aktuelle Middleware-Technologien gehört das Angebot von verteilten Transaktionen zum Standard-Umfang. Im Falle von J2EE wird beispielsweise die Java Transaction API (JTA) angeboten. 2.3.3 Sicherheitsdienste Aufgrund der Kommunikation über unsichere Kanäle, wie etwa über das Internet, besitzt der Aspekt der Verschlüsselung insbesondere beim Versand vertraulicher Daten eine hohe Relevanz. Aus diesem Grund stellen einige Middleware-Produkte standardisierte oder proprietäre Verschlüsselungsprotokolle wie im Fall der standardisierten etwa SSH oder HTTPS zur Verfügung. Bei der Verschlüsselung wird unterschieden in: Symmetrische Verfahren Der Schlüssel zur Verschlüsselung ist Entschlüsselung. Beispiel: DES identisch mit dem Schlüssel zur Asymmetrische Verfahren Die beiden Schlüssel unterscheiden sich. Für die Verschlüsselung wird ein Öffentlicher Schlüssel verwendet, für die Entschlüsselung ein Privater Schlüssel. Beispiel: RSA Mit dem Erstarken von Verteilten Anwendungen steigt auch die Anonymität der Kommunikationspartner untereinander, insbesondere im Bereich von BusinessAnwendungen. Durch das Konzept des öffentlichen Schlüssels, der jedem potentiellen Kommunikationspartner leicht zugänglich gemacht werden kann, eignen sich die asymmetrischen Verfahren besonders für die Anforderungen in großen, anonymen Netzen. Neben der Verschlüsselung steigt aber auch die Bedeutung von Authentisierung der Kommunikationspartner, also die Feststellung ob eine Instanz auch tatsächlich diejenige ist, die sie vorgibt zu sein. Auf diese Thematik wird beispielsweise in [3] detailliert eingegangen. - 21 - 2.4 Architekturprinzipien Ein großes Interesse eines jeden Ingenieurs besteht darin, auf Basis bestimmter Kriterien ein komplexes System in kleinere Einheiten zu unterteilen, die so besser beherrschbar sind. Dieses Prinzip wurde bereits beim Komponentenmodell kennen gelernt. Im Falle von Verteilten Anwendungen wird als Kriterium schlichtweg die Zuständigkeit für eine bestimmte Teilaufgabe innerhalb des Gesamtsystems angeführt. Je nachdem, wie weit man diese Zuständigkeit selbst wieder untergliedert, ergibt sich eine bestimmte Anzahl so genannter Schichten (Tiers). Somit wird auch von mehrschichtigen Systemen gesprochen. Die einzelnen Schichten können dabei auf unterschiedliche Rechner verlagert werden. 2.4.1 2-Schichten Architektur Die einfachste Klasse von mehrschichtigen Systemen ergibt sich unmittelbar aus dem Wesen des klassischen Client-/Server-Modells mit den beiden Rollen des Diensterbringers (Server) und des Dienstnutzers (Client). Welche konkreten Aufgaben jeweils zu welcher Schicht zugeordnet werden, ist hierbei noch nicht definiert, entscheidend ist nur, dass zwei Aufgabenfelder mit potentiell zahlreichen Unteraufgaben existieren. Beispielsweise kann der Server ausschließlich für die Datenhaltung zuständig sein und dem Client auf Anfrage Daten liefern oder aber er kombiniert diese Funktionalität mit zusätzlicher Anwendungslogik. Ein Szenario einer 2-Tier-Architektur ist in Abbildung 13 dargestellt. Client Server Präsentation Anwendungslogik Anwendungslogik Daten Daten Abbildung 13: 2-Tier-Architektur Eine 2-Schichten-Architektur findet sich überwiegend nur in kleinen, überschaubaren Anwendungen, mit einfacher Nutzerinteraktion und einfachem Datenmodell. Ein maßgeblicher Nachteil ist dabei, dass bei einer kleinen Änderung innerhalb etwa des Datenmodells oder der Anwendungslogik die komplette Anwendung erneuert werden muss. Der vorliegende Abstraktionsgrad von Teilbereichen ist schlichtweg zu gering, um größeren Szenarien zu genügen. - 22 - 2.4.2 3-Schichten Architektur Durch die Einführung einer weiteren Schicht wird ein hohes Maß an zusätzlicher Flexibilität erzielt. Eine typische Unterteilung bilden die drei Schichten: Präsentationsschicht (View) Applikationsschicht (Controller) Datenschicht (Model) In diesem Zusammenhang wird auch vom Model-View-Controller Pattern (MVC) gesprochen. Dabei geschieht der Zugriff der Präsentationsschicht auf Daten nur noch über die Applikationsschicht. Abbildung 14 zeigt eine Anwendung basierend auf dieser Architektur. Client Server Datenbankserver Präsentation Anwendungslogik Firewall Daten Abbildung 14: 3-Tier-Architektur Die Schichten bieten nach außen hin definierte Schnittstellen an, über die sie zugänglich sind. Bei einer Änderung innerhalb einer Schicht, ist bei gleich bleibender Schnittstelle damit eine Modifikation einer anderen Schicht nicht erforderlich. 2.4.3 n-Schichten Architektur Prinzipiell ist der Anzahl von Schichten keine Grenze gesetzt. Innerhalb der im letzten Absatz genannten Aufteilung kann beispielsweise die Applikationsschicht in weitere Schichten untergliedert werden. Dies ist ganz im Sinne komponentenbasierter Verteilter Anwendungen, bei denen Teilfunktionalitäten auf unterschiedlichen Rechnern eine gemeinsame Aufgabe erfüllen. Ebenso ist es denkbar die eigentliche Logik der Anwendung von der Logik für den Datenzugriff zu separieren und innerhalb zwei verschiedener Application-Server ablaufen zu lassen. - 23 - 2.4.4 Clients Bisher wurde die gesamte verteilte Anwendung mit dort vorhandene Klassifizierungen betrachtet. An dieser Stelle wird ein kurzer Blick auf die Clientseite geworfen. ClientAnwendungen lassen sich anhand ihrer Komplexität kategorisieren in: Fat-Client-Architekturen Thin-Client-Architekturen Fat Clients Bei diesen handelt es sich um Programme, die neben reinen Präsentationsaufgaben auch zusätzliche Anwendungslogik implementieren. Häufig finden sie sich in 2-Tier-Architekturen wieder. Sie führen zu folgenden Problemen: - Sicherheitsprobleme; Logik kann vom Client manipuliert werden Softwareverteilungsprobleme; Nutzer muss über Client-Programm verfügen Gefahr der zu starken Kopplung von Präsentation und Logik Thin Clients Lösung für die genannten Probleme bieten so genannte Thin Clients, bei denen analog die Präsentationsaufgaben deutlich im Vordergrund stehen. Das bekannteste Beispiel eines Thin Clients ist der Webbrowser, der in den meisten Fällen ausschließlich z.B. HTML- oder XMLInhalte darstellen soll. - 24 - 3 Beispiele: Ausprägungen verteilter Systeme Nachdem nun einige grundlegende Konzepte und Begriffe angesprochen wurden, werden in der Folge zwei konkrete Formen Verteilter Anwendungen behandelt. Zunächst wird dabei auf Webanwendungen im Allgemeinen kurz eingegangen und daraufhin die in letzter Zeit deutlich an Bedeutung gewinnenden Webservices samt ihrer Protokolle dargestellt. Webservices sind Gegenstand des Praktikums. 3.1 Webanwendungen Webanwendungen bestehen im einfachsten Fall aus einem Webserver, der bestimmte Inhalte, wie etwa HTML-Seiten anbietet und einem Webbrowser zur Darstellung dieser Inhalte auf Clientseite. Die Übertragung erfolgt auf Basis des standardisierten HTTP-Protokolls. Dieses ist ein simples Request-/Reply-Protokoll, basiert also auf einem Anforderungs- und einem Antwortvorgang. Der Ablauf ist in Abbildung 15 dargestellt. Client 1 Webbrowser Webserver Dokumente 2 Logik Präsentation Abbildung 15: Request-/Reply-Protokoll HTTP 1. Ein Webbrowser fordert hier zunächst mit einem HTTP-Request ein bestimmtes Dokument durch Angabe der Adresse an. 2. Der Webserver sendet das gewünschte Dokument per HTTP-Response zurück, was beim Client direkt angezeigt wird. Das angeforderte Dokument kann entweder schon in übertragbarer Form auf Serverseite vorliegen oder aber wird dynamisch generiert (in Abbildung 15 durch Pfeil auf Server-Seite verdeutlicht). Für die dynamische Generierung stehen zahlreiche Möglichkeiten, wie CGIProgramme, PHP oder Servlets zur Verfügung. Zudem kann der Webserver selbst wiederum andere Server nutzen, wie etwa einen Datenbankserver, um dynamisch Daten in eine HTMLSeite einzubringen. 3.2 Webservices Ein Webservice scheint auf den ersten Blick einer klassischen Webanwendung zu gleichen, insbesondere die Bezeichnung „Webservice“ suggeriert eine Ähnlichkeit. Ein Webservice ist allerdings in seinem Wesen und seiner Zielsetzung grundverschieden. - 25 - Webanwendungen haben das Ziel, Menschen Daten aufbereitet zu präsentieren und Inhalte darzustellen, während Webservices auf eine Kommunikation zwischen Business-Logik abzielen, vor allem innerhalb einer stark anonymen Umgebung. Webservices gehören zu den Service Oriented Architectures (SOA), bei denen eine Menge unabhängiger, lose gekoppelter Services zur Implementierung der Gesamtapplikation verwendet wird. Ein Szenario zur Verdeutlichung zeigt Abbildung 16. Reisebüro Webservice eines Hotels Client Webserver Webbrowser Webservice einer Fluggesellschaft WebserviceInfrastruktur Webservice einer Autovermietung Abbildung 16: Webservice-Szenario Hier greift eine Client-Anwendung mittels Webbrowser auf die Webseiten eines Reisebüros zu. Per Webservice interagiert daraufhin die Anwendungslogik auf dem Webserver mit weiteren Servern, um Angebots-Informationen von Business-Partnern zu erhalten. Das Innovative an diesem Ablauf ist die Standardisierung der Interaktion und die eigenständige Suche der Anwendungslogik des Reisebüro-Servers nach geeigneten Teildiensten (Flugbuchung, Hotelbuchung, …) bei anderen Anbietern. Webservices sind Dienste, die über definierte Schnittstellen zugänglich sind und bestimmten Standards genügen. Webservices basieren auf den vier standardisierten Protokollen bzw. Formaten XML, WSDL, SOAP und UDDI. Sie verursachen zwar einen großen Overhead bei der Kommunikation, bieten aber dafür eine enorme Mächtigkeit. 3.2.1 XML Die Extensible Markup Language (XML) ist eine deskriptive Sprache, die hauptsächlich zur Beschreibung von Datenstrukturen eingesetzt wird. Daten werde dabei in normalen Textdateien abgelegt, die bestimmte Strukturanforderungen erfüllen und sowohl für Menschen, als auch für einen Parser leicht lesbar sind. Ein Dokument, das alle XML-Regeln einhält, wird als wohlgeformt bezeichnet. - 26 - Eine XML-Datei hat beispielsweise folgenden Aufbau: <?xml version="1.0" encoding="UTF-8"> <Reise> <Flugreise> <Reiseziel>Moskau</Reiseziel> <Airline>Moskau Air</Airline> <Preis>1000</Preis> </ Flugreise> < Flugreise> <Reiseziel>Berlin</Reiseziel> <Airline>Berlin Air</Airline> <Preis>100</Preis> </ Flugreise> <Schifffahrt> <Reiseziel>New York</Reiseziel> <Schiffname>Tirpitz</Schiffname> <Preis>2000</Preis> </Schifffahrt> </Reise> Abbildung 17: Beispiel einer XML-Datei Sie besteht aus einem Kopf und einem Rumpf. Der Kopf definiert einige Metainformationen wie Versionsangaben und Zeichensatz. Der Rumpf enthält innerhalb von Tags die eigentlichen Daten, die beliebig tief verschachtelt sein können. Sowohl WSDL, als auch SOAP entsprechen dem XML-Standard. Für nähere Informationen zu XML siehe [4]. 3.2.2 WSDL Wie auch bei früheren Entwicklungen, etwa dem RPC, muss ein Client darüber informiert werden, wie der Dienst über seine Schnittstelle genutzt werden kann. Die Beschreibung dieser Schnittstelle erfolgt dazu bei Webservices in der Web Services Description Language (WSDL). Dieses Format ist sowohl sprach- als auch plattformunabhängig. Eine ausgereifte WebserviceInfrastruktur ermöglicht die automatische Generierung einer WSDL-Beschreibung aus den Programmdateien des Webservices, wie es etwa bei Microsoft .NET der Fall ist. Um eine Kommunikation zu ermöglichen generiert ein Client aus der publizierten WSDLDatei einen Proxy, der dann zur Ansteuerung des Webservices verwendet wird. Eine WSDL-Beschreibung enthält neben Informationen über benötigte Datentypen und für den Aufruf verfügbare Protokolle genaue Angaben über die nutzbaren Methoden samt Parameter und Rückgabewerte. Diese werden innerhalb von Tags des Typs <wsdl:operation> angegeben. Für umfangreiche Informationen zu WSDL siehe [5]. - 27 - 3.2.3 SOAP Das SOAP-Protokoll dient dem Aufruf eines Webservices bzw. der Rückgabe von Ergebnissen. Es löst den XML-RPC ab. Das Protokoll beschreibt dabei die Struktur der Nachrichten. Der Aufbau einer SOAP-Nachricht ist in folgender Abbildung 18 schematisch dargestellt. SOAP-Envelope SOAP-Header Metainformationen SOAP-Body Daten Abbildung 18: Aufbau einer SOAP-Nachricht Dabei werden Metainformationen wie etwa Informationen über Verschlüsselung im Header und die eigentlichen Daten im Body innerhalb eines SOAP-Envelopes gekapselt. Die Übertragung von SOAP-Dateien erfolgt mittels eines Trägerprotokolls, bei dem es sich in den meisten Fällen um HTTP in Kombination mit TCP handelt. Die Kommunikation über HTTP ermöglicht auf einfache Weise das Passieren von Firewalls in abgesicherten Netzen. Für weitere Informationen zu SOAP siehe [6]. 3.2.4 UDDI Wie bereits angedeutet ist die dem Webservices zugrunde liegende Vision eine MaschineMaschine-Kommunikation, bei der ein Rechner bei Bedarf eigenständig im Internet einen Service sucht und verwendet. Neben der Schnittstellenbeschreibung und einem Zugriffsprotokoll muss ein Webservice somit auch auffindbar sein. Für diesen Zweck wurde Universal Description, Discovery and Integration (UDDI) geschaffen. An der Organisation dieses Verzeichnisdienstes erkennt man bereits die Zentrierung auf Business-To-Business (B2B) - Anwendungen. Einem Unternehmen wird es ermöglicht, sich in ein Namensregister (White Pages) und ein Branchenverzeichnis (Yellow Pages) einzutragen und genaue Informationen zu den angebotenen Webservices zu geben (Green Pages). Bei den Suchkriterien können sowohl technische, als auch unternehmenspolitische Aspekte und Anforderungen zur Auswahl des Kommunikationspartners berücksichtigt werden. Die Publikation von Webservice-Schnittstellen an einen UDDI-Dienst bzw. die Informationslieferung an einen Client findet auf Basis von WSDL statt. - 28 - Damit im Internet global eine eindeutige Beschreibung von Webservice-Angeboten erfolgen kann, sieht UDDI eine enge Kooperation zwischen den so genannten UDDI-Operatoren vor. Für Informationen zur UDDI-Spezifikation siehe [7]. 3.2.5 Ablauf einer Webservice-Kommunikation Das Zusammenspiel der vier Standards ist in Abbildung 19 dargestellt. UDDI-Verzeichnisdienst WebserviceKonsument Datenbestand WSDL 2 1 Benötigte Funktionalität WSDL Webservice-Anbieter Proxy SOAP 4 3 Webservice Webservice … Abbildung 19: Ablauf einer Webservice-Kommunikation Der Ablauf ist dabei folgendermaßen: 1. Ein Webservice-Anbieter macht die angebotenen Dienste bei einem UDDIVerzeichnisdienst bekannt. 2. Ein Client ermittelt mittels UDDI einen Anbieter für einen bestimmten Dienst und bekommt die WSDL-Beschreibung geliefert. 3. Aus der WSDL-Beschreibung des Anbieters generiert er einen Proxy. 4. Der Webservice wird über SOAP genutzt. Die Verwendung eines Webservices wird auch als Konsumieren bezeichnet. Ist dem Client ein Webservice-Anbieter bekannt, so erfolgen natürlich nur Schritte 3 und 4. Die WSDL-Beschreibung erhält er dabei unmittelbar vom Webservice-Anbieter. - 29 - Teil II 4 Grundlegendes Für den zweiten Teil der Abhandlung werden die theoretischen Grundlagen der im Komplex II – Programmierung verteilter Anwendungen - des Praktikums angesprochenen Technologien vorausgesetzt. Die dort behandelten fünf Ansätze werden in der Folge in ihrer Bedeutung und ihrem Einsatzgebiet zusammenfassend eingeordnet und in einen Gesamtzusammenhang gestellt. Auch hier ist der Fokus auf einige zentrale Aspekte gerichtet. Aufgrund der teils sehr unterschiedlichen Mächtigkeit der Technologien wird die Abhandlung untergliedert. Es ist zunächst CORBA und Java-RMI beschrieben, daraufhin der Weg von COM zu .NET aufgezeichnet und schließlich die beiden mächtigen Plattformen .NET und J2EE in Kernpunkten gegenüber gestellt. 5 Corba und Java-RMI Bei grober Betrachtung der Struktur und der Zielsetzung von Java-RMI und CORBA erscheinen beide Technologien zunächst unterschiedlich. Auf der einen Seite handelt es sich bei Java-RMI um einen Kommunikationsmechanismus, der speziell auf die Sprache Java zugeschnitten ist. Demgegenüber steht auf der anderen Seite das sprachunabhängige und durch einen offenen Standard bestimmte CORBA. 5.1 Unterschiede Einige wichtige Unterschiede sind in der folgenden Tabelle 2 zusammengetragen. CORBA RMI Sprache sprachunabhängig fokussiert auf Java Schnittstellenbeschreibung IDL Java Interfaces Generierung von Stub/Skeleton aus IDL aus übersetztem entfernten Objekt Garbage Collection nicht im definiert; Services Übertragungsprotokoll IIOP Ursprünglich JRMI, ergänzt durch IIOP Namensdienst CORBA-Namensdienst des ORB rmiregistry, JNDI, … Plattform jede, auf der ein CORBA ORB zur Verfügung steht jede, auf der eine Java 2 VM vorhanden ist Standard implizit explizit vorhanden durch Tabelle 2: Vergleich CORBA und Java-RMI - 30 - nun Neben den genannten Kriterien lassen sich noch zahlreiche weitere identifizieren, wie etwa die Schwierigkeit der Unterstützung bestehender Anwendungen, die bei CORBA aufgrund der Sprachunabhängigkeit leichter gelingt, als bei Java RMI. Wie in der Tabelle erwähnt, wurde bei Java RMI zunächst ausschließlich das spezialisierte Protokoll JRMI zur Kommunikation verwendet. Damit eine Interoperabilität zwischen RMI und anderen Technologien, eben insbesondere CORBA ermöglicht wird, wurde zusätzlich die Unterstützung für IIOP implementiert. Das Designziel des Protokolls ist die Möglichkeit der Kommunikation unterschiedlichster Objekte, von deren zugrunde liegenden Technologie abstrahiert werden soll. Diese Interoperabiltät geht allerdings zu Lasten der Effizienz. Die Möglichkeit aus der IDL-Beschreibung eines entfernten Objekts den Client-Stub zu generieren, vereinfacht die Distribution des Stubs. Die IDL-Beschreibung kann auf unterschiedliche Weisen einem Client zugänglich gemacht werden, wie beispielsweise über einen FTP-Server oder mittels eines UDDI-Registers, das nicht auf WSDL-Inhalte beschränkt ist. Bei Java-RMI gestaltet sich der Zugang zum Stub schwieriger, da er aus der kompilierten Klasse des entfernten Objekts generiert wird. Diese ist dem Client gewöhnlich nicht zugänglich. Abbildung 20 beschreibt den RMI-Mechnismus zum Download des Client-Stubs. Abbildung 20: Download des Client-Stubs bei Java-RMI (aus [11]) Wie hier zu sehen ist, wird die Anfrage nach der Klasse dynamisch zur Laufzeit gestellt. Zur Übertragung bestehen mehrere Möglichkeiten, allerdings empfiehl Sun das HTTP-Protokoll aufgrund der damit verbundenen Flexibilität und Einfachheit der Bereitstellung. 5.2 Gemeinsamkeit Trotz der Unterschiede beim Entwicklungsprozess, der Systemunterstützung und den Vorgängen bei der Kommunikation sind sich CORBA und Java RMI letztendlich sehr ähnlich. Die Object Management Group bezeichnet Java-RMI in [10] gar als einen ORB, dem allerdings die CORBA-Konformität fehle. Beide Systeme bilden eine Konsequenz aus der Forderung nach einem intuitiven Kommunikations-Modell. Dabei erreichen sie eine hohe Transparenz sowohl für den Entwickler, als auch für den Anwender. Viele Low-Level-Details der Kommunikation bleiben - 31 - verborgen. Der zusätzliche Codeaufwand für die Verteilung eines Objekts bzw. die Nutzung eines verteilten Objekts ist gering. Zudem erfährt der Erstellungsprozess einer Anwendung in beiden Fällen eine starke Werkzeugunterstützung. CORBA war ursprünglich als vollständige Plattform mit umfangreicher Dienstunterstützung für Anwendungen konzipiert. Diesen Anspruch konnte es allerdings nicht gerecht werden. Gründe dafür liegen weniger auf der technologischen, als auf der politischen Ebene. Nach wie vor spielt CORBA aber insbesondere aufgrund seiner Broker-Architektur eine Rolle. CORBA-Produkte, vor allem im Open-Source-Bereich, werden weiterentwickelt, allerdings ist deren Hauptanwendung die Einbeziehung in umfassendere Plattformen, wie etwa J2EE, um diese zu Integrations-Plattformen zur Unterstützung beliebter Technologien zu machen. Ähnliches gilt für Java-RMI, das für die Implementierung vollständiger Anwendungen kaum Bedeutung hat. Allerdings hat sich Java-RMI eine zentrale Aufgabe in J2EE für die Kommunikation zwischen Teilsystemen, wie etwa zwischen einem entfernten Client und dem Java Naming and Directory Interface (JNDI) oder mit EJBs, gesichert. Somit ist beiden Technologien gemeinsam, im Sinne von ausgereiften Kommunikationsinfrastrukturen im Anwendungsumfeld komplexer Plattformen eingesetzt zu werden. 6 Von COM zu .NET In den neunziger Jahren stellten COM und die darauf aufbauenden Technologien die Basis für Anwendungen auf der Windows-Plattform dar. Durch zum einen wirtschaftlichen Druck von Konkurrenzentwicklungen und zum anderen durch technologische Mängel baute Microsoft COM nicht weiter aus, sondern erschloss mit .NET einen neuen Weg der Entwicklung von Anwendungen samt den zugrunde liegenden Prinzipien. Welche größten Schwächen COM+ hat bzw. wie .NET diese behebt und wie .NET mit COM+ interagiert, wird in der Folge erläutert. 6.1 Schwächen von COM+ Wie im Praktikumsversuch festgestellt werden kann, ist die Anwendungsentwicklung mit COM+ sehr stark an traditionelle Microsoft-Mechanismen gebunden, während .NET neuartige Konzepte wie die Common Language Runtime einführt und damit eine Abstraktion von der eigentlichen Betriebssystemebene schafft. Eine Komponente muss samt ihrer Metainformationen wie Versionsangaben, Schnittstellen etc. explizit registriert werden. Dies geschieht mittels eines eindeutigen Identifiers in der Windows-Registry. Die zentrale Speicherung von Informationen birgt eine gewisse Unflexibilität in sich. Die Inbetriebnahme von Komponenten wird erschwert, da sie sich dem System gegenüber vor der Verwendung publik machen müssen. Falls mehrere, inkompatible Versionen auf einem System betrieben werden sollen, scheitert der Mechanismus. Dieser Umstand wird als DLL-Hölle bezeichnet. Demgegenüber hat man sich bei .NET für eine dezentrale Speicherung der Metainformationen in den Assemblies selbst entschieden. Neben der umständlichen Registrierung differiert die Form der Beseitigung nicht mehr benötigter Objekte ebenfalls von .NET. Die Verantwortung für die Garbage Collection wird bei COM indirekt dem Programmierer übergeben. Er muss mit Hilfe der beiden Methoden - 32 - AddRef() und Release() die Anzahl der für ein Objekt vorhandenen Referenzen durch einen Zähler mitprotokollieren. Erreicht ein Zählerstand den Wert null, so wird das entsprechende Objekt gelöscht. Zwar hat dies den Vorteil, dass ein Objekt unmittelbar, wenn es nicht mehr benötigt wird, auch entfernt wird, allerdings ist der Weg zum einen fehleranfällig und zum anderen besteht die Gefahr von zyklischen Objektreferenzen. Liegen zyklische Referenzen vor, so können die daran beteiligten Objekte, obwohl sie in der Anwendung nicht mehr benötigt werden, nicht entfernt werden. Die Erkennung von Zyklen ist nicht trivial. Bei .NET erfolgt eine vollkommen automatische Speicherverwaltung durch die CLR. Dabei wird in periodischen Abständen ausgehend von Wurzelreferenzen, wie etwa globalen oder statischen Referenzen einer Anwendung, ein Baum aller erreichbaren Objekte aufgebaut. Nach diesem Schritt werden alle Objekte, die nicht im Baum enthalten sind, vom Heap entfernt. Ein weiteres Problem bei COM und seinen Nachfolgern stellt das verwendete Typsystem dar. COM hat den Anspruch, sprachunabhängig zu sein. Eine Komponente kann in einer beliebigen Programmiersprache geschrieben sein, sofern ein Mapping zwischen dieser Sprache und der MIDL existiert. Tatsächlich werden bei der Interaktion zwischen Programmkomponenten mit unterschiedlichen Typsystemen die Typen durch das COMSystem aneinander angepasst. Dies ist ein recht aufwendiger Vorgang, der insbesondere Zeit kostet und somit zur Ineffizienz beiträgt. .NET umgeht das Problem, indem einfach ein kleinster gemeinsamer Nenner in Bezug auf das Typsystem durch das CTS definiert wird. Dadurch wird eine Interoperabilität auf SprachEbene unterstützt. Grundlegende Funktionalitäten sind bei COM durch die sehr umfangreiche Win-API bereitgestellt. Diese ist mit den einzelnen Windows-Versionen in der Komplexität stark angestiegen. Neben der Unübersichtlichkeit ist sie zudem nicht objektorientiert. Dieser Misstand wird durch .NET und seine Klassenbibliothek beseitigt. Die genannten Punkte machen COM+ zu einer schwerfälligen und unintuitiv handhabbaren Technologie. .NET räumt dabei mit vielen Problemen auf. Inwiefern die Lösungen dem größten Konkurrenten, der J2EE-Plattform entsprechen, wird weiter unten untersucht. 6.2 Interoperabilität zwischen COM und .NET Da sehr viele Investitionen in Software auf Basis von COM getätigt wurden, .NET allerdings COM nicht unmittelbar unterstützt, sind Möglichkeiten geschaffen worden, COMKomponenten aus .NET-Assemblies zu verwenden bzw. .NET-Funktionalitäten COM zur Verfügung zu stellen. Für beide Richtungen werden so genannte Wrapper eingesetzt. Dabei unterscheidet man: 1. COM Callable Wrapper (CCW) Ermöglichen die Verwendung einer .NET Assembly aus einer COM-Komponente. 2. Runtime Callable Wrapper (RCW) Ermöglichen die Verwendung von COM-Komponenten aus einer .NET Assembly. Die Erstellung der Wrapper erfolgt mit Werkzeugunterstützung. Dabei wird eine COM-DLL bzw. eine .NET Assembly generiert, die Aufrufe transparent an die jeweilige reale Komponente weiterleitet. - 33 - 7 .NET im Vergleich zu J2EE Bei der Betrachtung der Struktur von .NET fällt an vielen Stellen die Ähnlichkeit zur J2EEArchitektur auf, deren Wesen dominiert ist durch die Eigenschaften von Java. Insbesondere durch die Abstraktion von der zugrunde liegenden Plattform durch die CLR und den damit verbundenen Konzepten, wie dem Zwischencode, verdeutlicht sich die strukturelle Annährung. Tabelle 3 zeigt die Gegenüberstellung zentraler Aspekte J2EE .NET Plattform plattformunabhängig überwiegend Microsoft Windows, allerdings auch freie Implementierungen Laufzeitumgebung Java Virtual Machine Common Language Runtime Sprachen Java C#, VB, C++, J#, Perl, F#, Haskell, … Kompilierter Code Java Bytecode Common Intermediate Language Kommunikationsprotokoll JRMI, IIOP, SOAP, … DCOM, SOAP, Remoting, ... Zwischencodeausführung Compilierung, Interpretation, hybride Ansätze, … JIT-Compilierung Interoperabilität mit anderen Sprachen Mittels CORBA, Java Native Interface (JNI) Unmittelbar unterstützt Entwicklungsumgebungen Eclipse, NetBeans, … Visual Studio Komponenten Enterprise Java Beans Assemblies Typdifferenzierung Unterscheidung in Referenz- Jeder Typ (Referenz- und und Werttypen mit Werttyp) ist mit Unterstützung durch System.Object kompatibel Wrapperklassen (Integer etc.) Tabelle 3: Vergleich J2EE und .NET Bei der Spezifikation der Virtuellen Maschine ist der wesentliche Unterschied die strikte Definition der Teilaufgaben (Speicherverwaltung, Threadunterstützung,...) der .NET VM. Durch die Freiheiten bei der Implementierung der Algorithmen und Mechanismen (siehe dazu [12]) der JVM gelingt eine besser Adaption an spezielle Anforderungen, beispielsweise an Eingebettete Systeme, die so etwa als Clients in einer J2EE-Applikation fungieren können. Auch bei der Ausführung des Bytecodes macht die JVM-Spezifikation keine näheren Ausführungen. Häufig werden hierzu hybride Ansätze angewandt, bei denen beispielsweise im Regelfall eine Interpretation des Bytecodes vollzogen wird. Falls allerdings bestimmte Methoden mehrfach ausgeführt wurden, so werden sie zur Effizienzsteigerung in nativen Code übersetzt. J2EE ist stärker darauf bedacht, komplexere, mehrschichtige Anwendungsstrukturen unmittelbar zu unterstützen. Dazu bietet es Enterprise Java Beans an. Diese separieren die Logik (Session Beans) von der Datenbasis (Entity Beans). Zudem wird dabei weiter in - 34 - unterschiedliche Formen dieser Einheiten gegliedert (statefull, stateless, …), um alle Anwendungsszenarien abzudecken. .NET ist dieses Konzept unbekannt. Beide Architekturen bieten eine umfangreiche Unterstützung durch mächtige Klassenbibliotheken. Für die meisten J2EE APIs bzw. Bibliotheken gibt es bei .NET Entsprechungen. Folgende Tabelle 4 zeigt einige Beispiele. J2EE .NET Sicherheit Java Authentication and Authorization Service (JAAS) System.Security Asynchrone Nachrichtenverarbeitung Java Message Service (JMS) Microsoft Message Queues (MSMQ) Arbeit mit XML Java API for XML System.XML Processing (JAXP), Java API for XML Registries (JAXR), … Direkter Datenbankzugriff Java Database Connectivity (JDBC) ADO.NET Tabelle 4: Gegenüberstellung von APIs aus J2EE und .NET Innerhalb der Laufzeitumgebung werden alle benötigten Dienste den Plattformen zur Verfügung gestellt. J2EE wird durch eine wesentlich umfangreichere Anzahl von unterschiedlichen Implementierungen des Application-Servers, wie etwa durch die Produkte IBM WebSphere, BEA Weblogic oder JBOSS unterstützt. .NET hingegen ist nach wie vor stark zentriert auf Microsoft Windows mit darauf laufendem IIS. Bei der Entwicklung von .NET gaben Java und insbesondere J2EE zahlreiche Anregungen. Der Trend zeigt dabei, dass nach wie vor im Bereich Verteilter Anwendungen auf die Steigerung der Abstraktion für Programmierer und Anwender gesetzt wird. Allerdings werden die dabei eingeschlagenen proprietären Lösungsansätze der Vergangenheit zunehmend durch standardisierte Verfahren ersetzt, wie etwa am Beispiel von Webservices, die von beiden Plattformen unterstützt werden, deutlich wird. Anstatt auf separierte Verfahren zu setzen, zielen .NET und J2EE auf die Integration verschiedener Systeme, Technologien und Architekturen ab. Sie erfüllen durch das Angebot zahlreicher Dienste alle Forderungen an eine komplexe anwendungsorientierte Middleware. - 35 - 8 Anhang 8.1 Abbildungsverzeichnis Nr. Titel Seite 1 Einordnung Verteilter Anwendungen 6 2 Beispiel einer Verteilten Anwendung 7 3 Kommunikation über Nachrichten 10 4 Ablauf einer Kommunikation mittels RPC 10 5 Stub-Generierung aus IDL-Datei 11 6 Directory-Service im RPC-System 12 7 Stellvertreter bei migrierten Objekten 14 8 Stellvertreter bei migrierten Objekten 16 9 Einordnung von Middleware 16 10 Namensorganisation 18 11 Verteilung der Kontexte auf unterschiedliche 18 12 Ablauf des 2-Phasen-Commit-Protokolls 19 13 2-Tier-Architektur 21 14 3-Tier-Architektur 22 15 Request-/Reply-Protokoll HTTP 24 16 Webservice-Szenario 25 17 Beispiel einer XML-Datei 26 18 Aufbau einer SOAP-Nachricht 27 19 Ablauf einer Webservice-Kommunikation 28 20 Download des Client-Stubs bei Java-RMI 30 8.2 Tabellenverzeichnis Nr. Titel Seite 1 Vergleich des Client-/Server- und objektorientiertem 13 Modell 2 Vergleich CORBA und Java-RMI 29 3 Vergleich J2EE und .NET 33 4 Gegenüberstellung von APIs aus J2EE und .NET 34 - 36 - 8.3 Abkürzungsverzeichnis Abkürzung Bedeutung ACID ADO API B2B CCW CGI CLR COM CORBA CTS DCOM DES EJB FTP HTML HTTP IDL IIOP IIS IP J2EE JAAS JAXP JAXR JDBC JMS JNDI JNI JRMI JTA JVM MIDL MSMQ ORB PHP RCW RMI RPC RSA SOA SOAP TCP UDDI UUID WSDL XML Atomicity, Consistency, Isolation, Durability ActiveX Data Objects Application Programming Interface Business-to-Business COM Callable Wrapper Common Gateway Interface Common Language Runtime Component Object Model Common Object Request Broker Architecture Common Type System Distributed Component Object Model Data Encryption Standard Enterprise Data Bean File Transfer Protocol Hypertext Markup Language Hypertext Transfer Protocol Interface Definition Language Internet Inter ORB Protocol Internet Information Server Internet Protocol Java 2 Platform, Enterprise Edition Java Authentication and Authorization Service Java API for XML Processing Java API for XML Registries Java Database Connectivity Java Message Service Java Naming and Directory Interface Java Native Interface Java Remote Method Invocation Java Transaction Service Java Virtual Machine Microsoft Interface Definition Language Microsoft Message Queue Object Request Broker PHP: Hypertext Preprocessor Runtime Callable Wrapper Remote Method Invocation Remote Procedure Call Rivest, Shamir, Adleman (asym. Kryptoalgorithmus) Service Oriented Architecture früher: Simple Object Access Protocol, keine Abkürzung mehr Transmission Control Protocol Universal Description, Discovery and Integration Universally Unique Identifier Web Services Description Language Extensible Markup Language - 37 - 8.4 Literatur [1] Computernetzwerke; Andrew S. Tanenbaum, Pearson Studium; 2003 [2] Skript zur Lehrveranstaltung Distributed Systems (Prof. Schill) [3] Netzsicherheit, Algorithmische Grundlagen und Protokolle; Günter Schäfer; Dpunkt Verlag; 2003 [4] http://www.w3.org/XML/ [5] http://www.w3.org/TR/wsdl.html [6] http://www.w3.org/TR/soap/ [7] http://www.oasis-open.org/committees/uddi-spec/doc/tcspecs.htm [8] Enterprise Java Beans 2.1; Martin Kompf ; Galileo Press ; 2004 [9] http://java.sun.com/j2se/1.5.0/docs/guide/rmi/spec/rmi-arch4.html [10] http://www.omg.org/library/wpjava.html [11] http://java.sun.com/j2se/1.4.2/docs/guide/rmi/codebase.html [12] http://java.sun.com/docs/books/vmspec/2nd-edition/html/VMSpecTOC.doc.html - 38 -