REST und Webhooks für einen Textchatserver

Teil 1: Modulare Softwarearchitektur – Vorteile anhand eines Textchatservers erklärt

Die technischen Komponenten eines Textchats werden grundlegend in zwei Kategorien aufgeteilt: Server und Client. Der Server verwaltet die Nachrichten und ist für deren Verteilung zuständig. Die Clients wiederum empfangen die Nachrichten und zeigen diese in der Regel dem Endnutzer an. Eine Besonderheit in diesem Modell stellt die Kommunikation der Komponenten dar. Beim Eintreffen einer neuen Nachricht muss der Server die entsprechenden Clients informieren. Doch nach welchem Muster wird eine Verbindung zwischen den Komponenten aufgebaut?
Gängige Implementierungen basieren auf dem Prinzip der ereignisgesteuerten Architektur, bei dem die Ereignisse Textnachrichten repräsentieren. Ein externer Broker stellt Kanäle bereit, die der Client abonnieren kann. Muss nun ein neues Ereignis an weitere Komponenten verteilt werden, sendet der Server die Daten in die entsprechenden Kanäle. Anschließend überträgt der Broker die Nachrichten an die abonnierten Clients.

REST-Schnittstelle und Webhooks

Leider ist die beschriebene Architektur nicht überall anwendbar. Beispielsweise erlaubt eine bestehende Infrastruktur keine bidirektionalen Verbindungen zwischen den einzelnen Komponenten. Um trotz solcher Einschränkungen einen Textchatserver zu betreiben, bedarf es einer Anpassung der Kommunikation. Für ein aktuelles Kundenprojekt stellten sich die Konzepte REST und Webhook als beste Alternative heraus.
Die REST-Schnittstelle wird für Clients bereitgestellt, zu denen nur eine unidirektionale Verbindung möglich ist, wohingegen ein Webhook eine bidirektionale Verbindung erfordert. Ein Client kann bei der REST-Schnittstelle des Servers zum Beispiel einen Textchat erstellen und neue Nachrichten senden. Eine Besonderheit stellt das Abfragen von neuen Nachrichten dar. Der Client fragt demnach in regelmäßigen Abständen an, ob der Server neue Nachrichten bereithält. Beim sogenannte Long Polling wird die Anfrage des Clients solange offengehalten, bis eine neue Nachricht eintrifft oder ein Timeout abgelaufen ist. Anschließend baut der Client eine neue Anfrage auf.
Auf der anderen Seite registriert sich der Client mit einem Webhook. Der Webhook gibt an, wohin neue Nachrichten gesendet werden sollen. Long Polling Aufrufe sind für diesen Client nicht mehr erforderlich. Trifft nun eine neue Nachricht ein, wird diese vom Server an den angebenden Webhook gesendet.

Besonderheiten REST-Schnittstelle

Um die weiteren Anforderungen des Textchatservers zu erfüllen, müssen beide Prinzipien individuell angepasst werden. Beispielsweise muss der Textchatserver erkennen, wann ein Teilnehmer die Verbindung verloren hat, damit der Textchat anschließend automatisch geschlossen wird. Bei den Webhooks können Timeouts oder Status Codes diese Funktion umsetzen. Bei der REST-Schnittstelle hingegen ist diese Form nicht möglich. Eine Lösung dieses Problems ist das Logging der Long Poll Aufrufe. Bei jedem Long Poll Aufruf speichert der Server das aktuelle Datum. Fragt der Client anschließend nicht mehr nach neuen Nachrichten, werden die anderen Teilnehmer über dessen Timeout informiert.
Eine weitere Besonderheit stellt die Implementierung des Long Polling dar. Nachdem der Aufruf beim Server eintrifft, prüft dieser, ob bereits neue Nachrichten zur Verfügung stehen. Für die Abfrage sendet entweder der Client einen Timestamp der letzten Nachricht oder die entsprechenden Zustände werden vom Server gespeichert. Letzteres erfordert jedoch eine weitere Implementierung, falls der Client aufgrund eines Verbindungsabbruchs ältere Nachrichten benötigt.
Sollten keine neuen Nachrichten zur Verfügung stehen, wird ein Thread für den Aufruf erzeugt, der anschließend pausiert wird. Um bei einer eintreffenden Nachricht entscheiden zu können, welcher Thread wieder aufgenommen werden muss, wird der Thread mit einem Identifikator markiert und in einer Datenstruktur temporär gespeichert. Ein Identifikator sollte ohne viel Aufwand anzeigen, für welchen Textchat und Nachrichtentypen der Thread zuständig ist.

Besonderheiten Webhooks

Auch die Implementierung des Webhooks ist nicht ohne Anpassungen verwendbar. Zuvor muss definiert werden, ob der Server jede Nachricht einzeln oder mehrere Nachrichten als Array gleichzeitig sendet.
Auch hier existiert das Problem der Synchronisation. Die Wiederaufnahme nach einem Timeout des Clients kann auf unterschiedliche Arten durchgeführt werden. Eine Möglichkeit wäre, alle vergangenen Nachrichten zu senden, wenn sich der Client erneut anmeldet. Alternativ werden nur die Nachrichten zurückgegeben, die ab dem Timeout versendet wurden. Wie auch bei der REST-Schnittstelle ist die Angabe eines Timestamps beim Beitreten vom Client möglich.

Fazit

Neben den gängigen Implementierungen eines Textchatservers konnte in dem beschriebenen Beispiel gezeigt werden, dass die erforderlichen Funktionen auch mit anderen Kommunikationsparadigmen umgesetzt werden können. Eine REST-Schnittstelle für unidirektionale Verbindungen und Webhooks für bidirektionale Verbindungen bilden in unserem Anwendungsfall die Grundlage der Implementierung. Auch spezielle Anforderungen, beispielsweise die Erkennung eines Timeouts, sind mit geringfügigen Anpassungen möglich.

Autor: Stefan Schomacker, Developer