Acceptor-Connector Das Acceptor-Connector Pattern trennt den Verbindungsaufbau zwischen zwei Peer-Services und der Verarbeitung, welche bei bestehender Verbindung durchgeführt wird. Kontext Ein Netzwerksystem oder Anwendung, welche verbindungsorientierte Protokolle für die Kommunikation zwischen Service-Endpunkten verwendet. Problem In verbindungsorientierten Netzwerksystemen besteht meist sehr viel Code, welcher die Verbindungen zwischen zwei Endpunkten initialisiert. Dieser Code ist aber mehrheitlich unabhängig von der erbrachten Dienstleistung der Services, welche bei bestehender Verbindung erbracht wird. Das Koppeln der Verbindungsinitiierung an die Anwendungslogik ist ungewollt weil: Es sollten verschiedene Verbindungsmodelle unterstützt werden können: z.b. ist es für die Erbringung der Dienstleistung nicht relevant, ob der Service die Verbindung aktiv (Initiator der Verbindung) oder passiv erstellt hat. Es sollten weitere Dienste hinzugefügt werden können, ohne das Änderungen am Verbindungsinitialisierungscode notwendig sind (sämtliche HTTP-Dienste können selbe Initialisierung verwenden). Die verwendeten Protokolle ändern häufiger, als die Logik für den Verbindungsaufbau, daher soll das Protokoll geändert werden können wobei der darunterliegende Verbindungsinitialisierungscode identisch bleibt. Für large-scale Netzwerkanwendungen soll die Latenz aufgrund der Verbindungsinitialisierung durch den Einsatz von erweiterten Betriebssystem-Funktionen wie asynchrone Verbindungsmechanismen reduziert werden können. Lösung Trennen des Verbindungsinitialisierungscode von der Verarbeitungslogik bei aufgebauter Verbindung. Die Anwendungs-Services sollen in peer service handlers gekapselt werden. Jeder peer service stellt die hälfte eines End-zu-End Service dar. Die Verbindung der peer-service sowie deren Initialisierung soll mittels den Factories Connector (für aktiven Verbindungsaufbau) und Acceptor (passiv Verbindungen akzeptieren) erfolgen. Nach Micha Reiser 1
dem Verbindungsaufbau werden die peer-services vom Acceptor / Connector initialisiert und das Handle für die Verbindung wird dem peer-service übergeben. Struktur Im Pattern sind sechs Komponenten involviert: Transport Endpoint z.b. Socket-Endpunkt. Ein Transport-Endpoint erlaubt das Lesen und Schreiben von Daten über die Verbindung. Transport Handle Identifiziert ein spezifischen Transport Endpoint. Z.B. ein Socket- Handle, aus welchem mittels recv Daten gelesen werden können (mittels dem Handle wird der Transport Endpoint identifiziert, von welchem die Daten dann gelesen werden). Service handler Definiert die eine Hälfte eines End-zu-End Dienstes. Ein konkreter Service spielt hierbei meist entweder die Client oder Server-Rolle, wobei auch beide Rollen simultan möglich sind (Peer-to-Peer). Der Service handler bietet eine Aktivierungsmethode, diese wird aufgerufen, sobald der Service verbunden wurde. Der Service hält ein Transport-handle. Acceptor Factory für das passive Akzeptieren von Verbindungen. Der Acceptor initialisiert einen passiven Transport Endpoint. Geht eine Verbindung ein, wird das zugehörige Transport Handle sowie der zugehörige Service handler initialisiert. Der Acceptor definiert zwei Methoden, connection initialize erstellt den passiven Transport Endpoint. connection completion wird aufgerufen, wenn eine Verbindung akzeptiert wird, initialisiert den Transport handle, erstellt einen Service handler und setzt den Transport handle auf dem service. Connector Der Connector stellt das aktive Pendant zu dem Acceptor dar. Er initialisiert eine Verbindung aktiv und wartet nicht auf den Eingang einer Verbindung. Der connection initialization Methode wird eine existierende Service handler Instanz übergeben. Der Connector etabliert dann eine aktive Verbindung zum gewünschten Endpunkt. Dispatcher Der Dispatcher ist zuständig für das demultiplexen von Ereignissen, welche verschiedene Service-Anfragen repräsentieren. Siehe hierzu das Reactor oder Proactor-Pattern. Ablauf Acceptor In der Abbildung 1 ist der Ablauf des Patterns unter Verwendung eines Acceptors ersichtlich. Micha Reiser 2
Abbildung 1: Ablauf bei der Verwendung eines Acceptors 1. Die Anwendung initialisiert den Acceptor (initialize connection). Dieser erstellt einen passiven Endpunkt. 2. Wenn eine Verbindung eingeht, wird auf dem Acceptor die connection completion Methode aufgerufen. 3. Der Acceptor erstellt nun das Handle für die Identifikation des Endpunktes (z.b. Socket-Handle). Zudem erstellt er eine Instanz des konkreten Service und initialisiert diesen mit dem Handle. Nun führt der Service die Anwendungsspezifische Logik aus. Connector In der Abbildung 2 ist der Ablauf des Patterns unter Verwendung eines Connector ersichtlich. 1. Die Anwendung weist den Connector an, eine aktive Verbindung für den übergebenen Service zu erstellen. 2. Der Connector liest das Handle (Ziel-Endpunkt) vom Service Handler aus und stellt die Verbindung mit diesem Endpunkt her. 3. Wurde die Verbindung hergestellt, ruft der Connector die Verarbeitungsmethode des Service-Handler auf. Micha Reiser 3
Abbildung 2: Ablauf bei der Verwendung eines Connectors Konsequenz Vorteile Wiederverwendbarkeit, Portabilität und Erweiterbarkeit: Da die Verbindungsinitialisierungslogik entkoppelt ist, kann diese, aber auch die Anwendungslogik wiederverwendet werden. Nur die Initialisierungslogik ist platformspezifisch. Fehlertoleranz: Die Trennung des Service-handler und des Acceptors stellt sicher, dass nicht fälschlicherweise das passive Endpoint-Handle zum Schreiben und Lesen von Daten verwendet wird. Effizienz: Das Pattern erlaubt das initialisieren sehr vielen Verbindungen (auch mit hoher Latenz), durch das asynchrone Aufbauen der Verbindungen. Nachteile Zusätzliche Indirektion: Fügt zusätzliche Indirektion ein, im Vergleich zur direkten Verwendung der Netzwerkschnittstelle. Sprachen wie C++, c#, Eiffel können diese Indirektion durch inlinen von Funktionen ggf. eliminieren. Erhöhte Komplexität: Für einfache Client-Anwendungen fügt das Pattern ggf. unnötige Komplexität hinzu (Overengineering). Kontrollfragen Kontrollfragen, welche mit Wahr / Falsch beantwortet werden sollen. Handelt es sich um zwei Aussagen ist für jede anzugeben ob richtig / falsch oder ob beide richtig sind und aus A B Micha Reiser 4
1. Kann durch die Anwendung des Acceptor-Connector-Pattern derselbe Service- Handler eine Dienstleistung für aktive sowie passive Verbindungen bereitstellen? 2. Der Connector behandelt passive Verbindungen Akzeptiert der Acceptor eine neue Verbindung, erstellt er eine Instanz des Service handler und übergibt diesem das Transport handle. 3. Erlaubt Acceptor-Connector Pattern sowohl die Wiederverwendung der Acceptor- Connectors sowie die Wiederverwendung der Service-Handler? Lösung: 1. Siehe Ja, 2. A=Falsch, B=Wahr, 3. Ja Micha Reiser 5