Inhalt
2. Anwendungsarchitektur
Im folgenden Kapitel wird zuerst kurz auf die generelle Anwendungsarchitektur einer peer-to-peer (p2p) Anwendung eingegangen. Danach wird die gewählte Architektur der Messenger-Applikation näher beschrieben. Ein weiteres Teilkapitel beinhaltet die Definition der Schnittstelle zwischen der Applikations- und der Kommunikationsebene im Messenger-Model. Zum Ende des Kapitels wird noch kurz auf die zugrunde liegende Testspezifikation der Messenger-Anwendung eingegangen.
2.1 Architektur
2.1.1 Die Peer-to-peer Architektur
"Peer-to-peer is a class of applications that take advantage of resources - storage, cycles, content, human presence - available at the edges of the Internet. Because accessing these decentralized resources means operating in an environment of unstable connectivity and unpredictable IP addresses, peer-to-peer nodes must operate outside the DNS and have significant or total autonomy of central servers." Clay Shirkey (The Accelerator Group) [dugaha]
Die p2p-Architektur ist bereits seit den siebziger Jahren bekannt und entstand zusammen mit der Internetentwicklung. Durch die verbesserte Rechenleistung und die jüngsten Veränderungen in der Technologie gab es Anfang der neunziger Jahre ein riesiges Neuaufkommen von p2p. Dies ist insbesondere auf den zwischenzeitlichen Erfolg von Musiktauschbörsen wie Napster oder Gnutella zurückzuführen. Diese beiden Anbieter nutzten die p2p-Technik um Dateien zwischen verschiedenen Clients auszutauschen.
Neben Napster und Gnutella bedient sich aber schon seit der Entstehung des Internets das IP-Routing-Protokoll der p2p-Architektur. Hierbei fungiert ein Router quasi als Peer, der mit den ihm bekannten anderen Peers Daten austauscht und somit eine Paketweiterleitung durchführt.
Besonderheiten der peer-to-peer-Architektur
Über eine p2p-Architektur erreicht man die verminderte Abhängigkeit von einem Server bzw. je nach p2p-Modell die völlige Serverfreiheit. Dadurch entgeht man der Zentralisierung der Serverkontrolle, da durch die direkte Verbindung unter den Usern eine höhere Selbstbestimmung möglich ist als in klassischen Client-Server-Architekturen. Aufgrund dieser direkten Verbindungen ist ein p2p-Modell auch flexibler und vielseitiger als ein Client-Server-Modell. Insbesondere ist durch das Zusammenscließen vieler Peers eine geballte Computerpower aufbaubar, sowie die Serverlast und der Bandbreitenverbrauch gleichmäßig unter den am verteilten System teilnehmenden Peers aufteilbar. In Bezug zu dem einleitenden Zitat von Clay Shirkey lässt sich die p2p-Archtekur als "Internet auf Applikationsebene" [dugaha] definieren. Insbesondere die Punkte der fehlenden zentralen Koordination, der verteilten Datenbasis, der globalen Sicht eines Peers auf das System und das autonome Auftreten eines Peers lassen diesen Vergleich zu.
Neben den vielen Vorteilen von p2p-Architekturen gibt es jedoch auch eine Reihe von Einschränkungen bzw. Nachteilen. So ist insbesondere die Lokalisierung von anderen Peers im Netz nicht so einfach zu lösen. Da keine zentrale Datenbasis vorhanden ist, müssen die gesamten für das System relevanten gespeicherten Daten ständig in jedem Peer verfügbar sein. In der später vorgestellten Messengeranwendung ist dies beispielsweise die Peerliste. Ein weiteres Problem besteht in der unzuverlässigeren Kommunikation gegenüber Client-Server-Architekturen. Peers und ihre Verbindungen sind nicht notwendigerweise verlässlich. Deshalb sind vor allem die Algorithmen etwas komplexer und es entsteht ein zusätzlicher Kommunikationsaufwand.
peer-to-peer-Modelle
Im Laufe der zeit haben sich vier mögliche peer-to-peer-Modelle entwickelt. Zum ersten ein reines p2p-Modell, bei dem auf jegliche zentrale Server verzichtet wird, wodurch ein dynamisches Finden von Peers im Netzwerk benötigt wird und der Entwickler die Möglichkeit hat, eigene Zugriffsregeln zu definieren. Zum zweiten ein p2p-Modell mit einem einfachen Discovery-Server, welcher die Peerliste zur Verfügung stellt. Der Verbindungsaufbau und die Kommunikation bleibt weiterhin Aufgabe des Peers. Insbesondere führt dieses Modell zu einer erhöhten Chance mehr Peers im Netz zu finden. Das dritte Modell ist ähnlich dem zweiten Modell. Es besteht jedoch aus einem weiteren Server, welcher Informationen über die verfügbaren Ressourcen bereitstellt. Dieser Server initiiert quasi die Kommunikation zwischen den Peers. Nach diesem Modell hatte Napster funktioniert. Das vierte und letzte p2p-Modell ist mit einer Client-Server-Architektur vergleichbar. Es handelt sich daher hier um keine direkte peer-to-peer Kommunikation mehr, da eine zentrale Ressourcenverwaltung im Server vorgenommen wird und somit wieder ein Single Point of Failure vorliegt.
![]() Abb. 3: p2p-Architekturmodelle nach [dream] |
2.1.2 Die Architektur der MessengeranwendungDie im Rahmen der Studienarbeit geplante und implementierte Messengeranwendung basiert auf einem reinen p2p-Modell. Die Wahl ist auf diese Architektur gefallen, da in den Anforderungen der Wunsch definiert wurde, ohne eine explizite Serverinstanz auszukommen. Um eine kommunikations- und plattformunabhängige Anwendung zu realisieren, wurde eine dreischichtige Softwarearchitektur gewählt. (siehe Abb. 4) |
|
Auf unterster Ebene befindet sich die Kommunikationsschicht. Sie stellt die Kommunikationsplattform für den Datenaustausch dar. Nähere Informationen über die hierbei eventuell möglichen und in der Anwendung implementierten Techniken folgen in Kapitel 3 - Technologie. Mittels eines definierten Kommunikationsinterfaces ist es der Applikationslogik möglich, sich der verschiedenen Implementierungen der Kommunikationsebene zu bedienen. Aufgabe der Applikationsebene ist es, die Funktionalität der Messenger-Applikation zur Verfügung zu stellen. Sie hält unter anderem die Information über vorhandene Chatpartner und die zur Zeit geöffneten Chats inklusive der teilnehmenden Partner. Zur Interaktion des Benutzers mit dem System wird auf die Applikationslogik ein grafisches User-Interface (GUI) aufgesetzt. Dieses dient ausschließlich zum Anzeigen und zum Entgegennehmen von Daten und Befehlen und beinhaltet keine weitere Programmlogik.
Dieser dreischichtige Aufbau ist auch in das Paketdiagramm übernommen worden, um die entsprechenden Klassen klar ihrem Aufgabengebiet zuordnen zu können.
Dem Benutzer ist es über eine entsprechende Konfigurationsdatei möglich auszusuchen, welches Kommunikationsmodell (hier: JXTA oder RMI) er benutzen möchte. Durch das definierte Kommunikations-Interface stellt sich die Wahl für die spätere Applikation völlig transparent dar. Ein Chat zwischen Partnern mit verschiedenen Kommunikationstypen ist jedoch nicht möglich. Des Weiteren macht sich die Wahl des Kommunikationstyps in der Reaktionsgeschwindigkeit der Applikation während des Chattens bemerkbar. Dies ist auf den unterschiedlichen Aufbau der Kommunikationstypen zurückzuführen. Speziellere Informationen zu den einzelnen Kommunikationstypen finden sich ebenfalls im Kapitel 3 - Kommunikationstechniken.
2.2 Schnittstellen
2.2.1 Die Schnittstelle zwischen System und Benutzer
Für die Kommunikation der Chat-Anwendung mit dem Benutzer wird eine grafische Benutzeroberfläche (GUI) zur Verfügung gestellt, welche beim Starten des Chats in der main-Methode der Klasse ChatApp erzeugt wird. Diese ist mittels des Singleton-Designpatterns implementiert. Somit ist stets nur eine Instanz der Klasse ChatApp im System vorhanden. Diese Instanz ruft - bei der Eingabe des Nicknames per Hand - eine Methode der MainGui auf, die ein Eingabefenster erzeugt, das dem Benutzer zur Namenseingabe zur Verfügung steht.
Im Hintergrund wird nun ein Communicator gestartet. Er ist für das Auffinden und das Verwalten der gefundenen Peers in einer Peerliste zuständig. Der eingegebene Nickname wird gegen die Peerliste auf Eindeutigkeit geprüft. Gegebenenfalls muss ein anderer Name angegeben werden. Eine genauere Aufruffolge der verwendeten Methoden ist den mittels OMONDO® erzeugten Sequenzdiagrammen im Anhang zu entnehmen.
Nun ist der Benutzer am System angemeldet. Wie erfolgt aber die Kontaktaufnahme und die Kommunikation mit den anderen angezeigten Chatteilnehmern? Dazu werden die gewünschten Teilnehmer in der Auswahlliste der MainGui selektiert und danach die Schaltfläche <Neuer Chat> betätigt. Es öffnet sich der Chatdialog, welcher im Titel die beteiligten Benutzer anzeigt. Bereits empfangene Nachrichten erscheinen im dafür vorgesehenen Anzeigefeld in der Mitte des Fensters.
Nach der Eingabe der Nachricht in das dafür vorgesehene Feld am unteren Rand des Fensters wird durch Betätigung des Button <Senden> die Übertragung durch den Benutzer ausgelöst. Dabei wird die Nachricht aus dem Chatfenster an die Klasse ChatApp übergeben, welche sie direkt an die Klasse Communicator weiterleitet. Der Communicator versendet die Nachricht an den bzw. die betreffenden Empfänger. Hier wird sie an die MainGui geleitet, welche sie im richtigen Chatfenster darstellt. Auch hier ist der genaue Ablauf im entsprechenden Sequenzdiagramm im Anhang dargestellt.
2.2.2 Das Kommunikationsinterface
Abb. 8 |
Um eine vom Kommunikationstyp unabhängige Chatanwendung zu implementieren, wird ein Kommunikationsinterface definiert, welches die Schnittstelle zwischen der Applikation als solches und der Kommunikation der beteiligten Peers untereinander darstellt. Aufgrund der Definition dieser einheitlichen Schnittstelle ist es möglich, die Kommunikation über verschiedene Techniken zu implementieren, ohne die Applikationslogik der Chatanwendung anpassen zu müssen. Weiterhin besteht somit die Möglichkeit über die Änderung eines Parameters in einer Konfigurationsdatei, die zum Programmstart ausgelesen wird, die Applikation mit unterschiedlichen Kommunikationstypen zu starten. Welche Kommunikationstypen in Frage kommen und welche in der besprochenen Chatanwendung implementiert werden wird im nächsten Kapitel ausführlich besprochen. Deshalb wird an dieser Stelle nur kurz auf den Aufbau der Schnittstelle eingegangen.
Die Methode initComm(String) wird nach dem Programmstart genutzt, um den Nickname zu überprüfen. Ist der Nickname im System noch nicht vorhanden, antwortet die Methode mit dem Wert "true". Wird der Wert "false" zurückgeliefert, ist der Benutzername bereits im System vorhanden und es muss ein anderer Name gewählt werden. Die Methode connectToPeer(Integer, String, Object) (siehe Abb. 8) wird für jeden beteiligten Peer an einem neu gestartetem Chat ausgeführt, um ihm die entsprechende Chat-ID und die Teilnehmer des neuen Chats mitzuteilen. Über sendMessage(Integer, String, String) wird eine Meldung an den adressierten Peer versendet.
Bleiben noch die Methoden closeChat(Integer, String) und shutDown(). Die erstgenannte Methode wird aufgerufen, wenn ein Chatfenster geschlossen wurde und setzt alle am Chat beteiligten Peers davon in Kenntnis. Letztere wird beim Beenden des kompletten Programms verwendet und meldet den eigenen Peer bei allen anderen Peers ab.
Wie die angesprochenen Methoden umgesetzt und implementiert werden hängt ganz von der verwendeten Technik ab. In der im Rahmen der Studienarbeit implementierten Chatanwendung wird das Interface durch die Klassen RmiCommunicator und JxtaCommunicator für die Techniken RMI und JXTA umgesetzt. Auch hier sei auf das nachfolgende Kapitel verwiesen, in dem die Besonderheiten bei den jeweiligen Implementierungen näher erläutert werden.
2.3 Testkonzeption
Um ein qualitativ hochwertiges Softwareprodukt zu erzeugen, wurde der Softwareentwicklungsprozess von entsprechenden Tests begleitet. Hierzu sind vor allem Modul- und Integrationstests durchgeführt worden. Die Modultests wurden dabei anhand von Prototypen durchgeführt. Bei Modulen, welche Schnittstellen zu anderen Modulen hatten, deren Funktionalität jedoch noch nicht zur Verfügung stand, wurden Stubs eingesetzt, welche die erwartete Funktionalität simulierten.
Ebenfalls auf der Ebene der Modultests können JUnit-Tests integriert werden. Bei dieser Art von Test wird zu einer existierenden Klasse eine entsprechende Testklasse erzeugt. In definierten Testfällen werden daraufhin beim Testdurchlauf die einzelnen Methoden der zu testenden Klasse aufgerufen und der Rückgabewert mit dem zuvor in der Testklasse spezifizierten Wert / Wertebereich verglichen. Werden die Spezifikationswerte eingehalten, gilt der Test als bestanden, ansonsten führt der JUnit-Test zu einer Fehlermeldung.
JUnit-Tests wurden im Rahmen der Studienarbeit nur für ausgewählte Klassen im Zusammenhang mit der Evaluation des MDA-Plugins objectiF® (siehe Kapitel 4.2.2) durchgeführt und nicht um die Anwendungsklassen auf Korrektheit zu überprüfen.
Zum Ende der Testphase wurden die im Dokument "Testspezifikation" ausgearbeiteten Testszenarien durchgeführt und deren Ergebnisse ausgewertet. Dazu wurde zum einen ein AdHoc-Netzwerk mittels WLAN-Technik mit 11 Mbit/s zwischen drei Rechnern aufgebaut, über das außer der Messengeranwendung keine weitere Kommunikation betrieben wurde, so dass die gesamte Netzperformance den Kommunikationsplattformen zur Verfügung stand. In einem weiteren Testdurchlauf wurde das WLAN-Netzwerk durch ein separates 100 Mbit/s-LAN ersetzt.








