Einführung in das Blocks Extensible Exchange Protocol

BEEP: verteilte Anwendungen entwickeln mit dem Baukasten für TCP/IP-Protokolle
Kommentare

Neue Anforderungen im Internet der Dinge (IoT) und durch Software as a Service (SaaS) werden von existierenden Netzwerkprotokollen oft nur unzureichend erfüllt. Es wird nach zukünftigen Standards gesucht, um das Problem zu lösen. Das Blocks Extensible Exchange Protocol (BEEP) bietet heute schon alles, was nötig ist. Warum also das Rad neu erfinden?

Das gibt es doch alles schon! Das Internet und die Verbindung zwischen Anwendungen basiert auf einer Vielzahl von Netzwerkprotokollen, jedes für sich spezialisiert auf einen bestimmten Anwendungsfall: FTP für die Übertragung von Dateien, SMTP für das Versenden von E-Mails oder HTTP für die Auslieferung von Webseiten und Daten über einen Internetserver. Warum sollte also etwas Neues gebraucht werden?
Bei solchen und ähnlichen Argumentationen im Projektalltag geht es um das Fundament verteilter Systeme, der Verbindung zwischen den Knoten. Hier lohnt es sich genauer hinzusehen, damit Probleme vermieden werden.

Jeder spricht mit jedem

Immer mehr Geräte, die Daten austauschen oder Dienste bereitstellen, werden miteinander verbunden. Dabei spielt es keine Rolle, ob es sich um einen Client oder einen Server handelt. Jeder Knoten im System kann sowohl Daten liefern als auch von einem anderen anfordern. Wird dafür das HTTP-Protokoll verwendet, muss jeder Knoten sowohl Client als auch Server sein. Daten fließen in beide Richtungen, und die Knoten sind gleichberechtigt. Es handelt sich dennoch nicht um eine Peer-to-Peer-Kommunikation, sondern um zwei Client/Server-Verbindungen. Eine Fehlerbehandlung wird dadurch erschwert, und das Potential für Störungen steigt mit Umfang und Komplexität der Kommunikation.
Sicherheit gewinnt im Internet zunehmend an Bedeutung. Es hat sich inzwischen durchgesetzt, Verbindungen zu verschlüsseln, damit sie nicht oder nicht so leicht angreifbar sind. Wer ungesicherte Verbindungen verwendet, läuft Gefahr, Opfer von Angriffen Dritter zu werden. Sicherheit ist also unbedingt erforderlich.
Um die Daten in dem beschriebenen Beispiel zu verschlüsseln, kann statt HTTP das HTTPS-Protokoll eingesetzt werden. Es muss jedoch jede der beiden Verbindungen gesichert werden, was doppelten Aufwand bedeutet.

Um sofortige Antwort wird gebeten

Die doppelte Verbindung ermöglicht eine Full-Duplex-Kommunikation. Anfragen sind gleichzeitig und unabhängig voneinander in beide Richtungen möglich. Damit ist bereits eine wichtige Forderung erfüllt. Jede Verbindung für sich betrachtet, wirft allerdings weitere Fragen auf.
Die einfachste Form über HTTP zu kommunizieren ist, vom Client eine Anfrage zu schicken und auf die Antwort zu warten. Die nächste Anfrage wird erst geschickt, wenn die vorige beantwortet wurde. Das reicht nicht aus, um eine schnelle und direkte Kommunikation zu implementieren. Durch Latenzzeiten entsteht schnell ein Stau, der das System verlangsamt, wenn nicht sogar lahmlegt. Eine Lösung für dieses Problem bietet Pipelining, das von HTTP/1.1 unterstützt wird. Anfragen können vom Client gestellt werden, ohne auf eine Antwort zu warten. Der Server beantwortet sie in der Reihenfolge, wie der Client sie schickt. Dadurch entsteht ein weiteres Problem, das als Head of Line Blocking (HOL) bezeichnet wird. Dauert die Bearbeitung einer Anfrage länger, müssen alle folgenden warten. Es entsteht erneut ein Stau bei der Kommunikation. Um hier Abhilfe zu schaffen, hilft Multiplexing (Abb. 1). Anfragen werden unabhängig voneinander (asynchron) beantwortet. Das von Google entwickelte SPDY-Protokoll unterstützt Multiplexing. Die SPDY-Funktionalität soll zukünftig in den neuen HTTP/2-Standard einfließen, um Performancetricks bei der Entwicklung überflüssig zu machen.
Die Möglichkeit, asynchrone Nachrichten über eine einzige TCP-Verbindung zu schicken, ist auch in anderen Protokollen nur selten zu finden. Gelöst wird das Problem, indem weitere Verbindungen aufgebaut und für die Übertragung unabhängiger Nachrichten verwendet werden. Daraus ergeben sich nicht nur Probleme bei der Authentifizierung und Sicherung, sondern auch Schwierigkeiten, Knoten über Firewallgrenzen hinaus miteinander zu verbinden.

Abb. 1: Techniken wie Pipelining und Multiplexing verbessern die Kommunikation von Anwendungen im Internet, jedoch setzen sie sich nur langsam durch

Abb. 1: Techniken wie Pipelining und Multiplexing verbessern die Kommunikation von Anwendungen im Internet, jedoch setzen sie sich nur langsam durch

Bitte warte auf mich

Auch wenn das gewählte Protokoll asynchrone Anfragen zulässt, muss nach einer festgelegten Zeit abgebrochen werden, weil der Client keine Möglichkeit hat, herauszufinden, ob noch eine Antwort vom Server kommen wird. Im Beispiel der beschriebenen Full-Duplex-Kommunikation mit zwei Verbindungen, kann über den Rückkanal der Fortschritt einer Anfrage gemeldet werden. Erst wenn diese Meldungen ausbleiben, muss die Bearbeitung der eigentlichen Anfrage abgebrochen werden. Die Zuordnung der Fortschrittsmeldungen zur eigentlichen Anfrage bedeutet jedoch, bei zwei unabhängigen Verbindungen, mehr Programmieraufwand. Darüber hinaus werden synchrone Fortschrittsmeldungen möglicherweise von anderen Aufrufen blockiert. Die Folge sind Timeouts und Abbrüche. Besser wäre es, wenn das verwendete Protokoll bereits auf eine Anfrage mehrere Antworten zulässt (Multi-Reply), die eine Überwachung der serverseitigen Verarbeitung ermöglichen. Ein Timeout wird dann nur zwischen den Einzelantworten festgelegt und nicht mehr für die gesamte Transaktion. Die im Internet häufig verwendeten Aktivitätsanzeigen können dann durch Fortschrittsbalken ersetzt und vom Server gesteuert werden.

Die Socket-Falle

Anforderungen moderner verteilter Systeme führen schnell an die Grenzen dessen, was die Implementierung einer Full-Duplex-Kommunikation mit Client-/Server-Protokollen zu leisten im Stande ist. Nicht selten wird dann ein eigenes Protokoll auf Basis von TCP-Sockets entwickelt. Dieser Weg birgt jedoch die Gefahr, den Aufwand zu unterschätzen, da alle Funktionen, die auf der Ebene des Anwendungsprotokolls benötigt werden, selbst programmiert werden müssen. Ein gutes Argument für die Verwendung des Socket-API ist sicher die Möglichkeit, Daten über eine Verbindung in beide Richtungen schicken zu können. Es ist auch reizvoll, alle Möglichkeiten zu haben, das Protokoll dem jeweiligen Anwendungsfall exakt anzupassen. Erkauft werden diese Vorteile durch hohen Entwicklungsaufwand und dem Risiko, zu viel (oder zu wenig) Zeit in das Protokoll zu investieren.
Die Vorteile, ein existierendes Protokoll zu verwenden, liegen auf der Hand. Es spart Zeit, die dann für die eigentliche Aufgabe, die eigene Anwendung zu implementieren, zur Verfügung steht. Der Preis sind Kompromisse bei der Funktionalität.

Stellen Sie Ihre Fragen zu diesen oder anderen Themen unseren entwickler.de-Lesern oder beantworten Sie Fragen der anderen Leser.

Ein Baukasten für Protokolle

Marshall T. Rose und Carl Malamud standen 1998 vor der Frage, wie dieses Problem in Zukunft gelöst werden kann. Das von M. Rose verfasste RFC3117 beschreibt die Designprinzipien und praktischen Erfahrungen, die in das BXXP-Protokoll einflossen, welches dann 2001 von der IETF als BEEP (Blocks Extensible Exchange Protocol) veröffentlicht wurde (RFC3080, RFC3081). BEEP bietet die notwendigen Funktionen, um synchron und asynchron Nachrichten auszutauschen. Es handelt sich dabei um eine echte Peer-to-Peer-Kommunikation (P2P). Zwei verbundene Knoten (Peers) können gleichberechtigt Nachrichten schicken und empfangen. Der Knoten, der die Verbindung aufbaut, wird Initiator und der wartende Knoten Listener genannt. Natürlich können mit BEEP auch Client-/Server-Verbindungen realisiert werden. Es ist ja nicht zwingend erforderlich, dass Nachrichten in beide Richtungen fließen. Ein Anwender kann Profile definieren, die die Art der Nachrichten und das Verhalten des Protokolls festlegen. Jeder Knoten stellt verschiedene Profile zur Verfügung, die alle über eine einzige Verbindung angesprochen werden. Ein BEEP-Profil zu definieren, ist der Mittelweg zwischen der Implementierung eines eigenen Protokolls und einer Lösung auf Basis existierender Protokolle.

BEEP und IoT

Mit dem Internet der Dinge werden Protokolle wie MQTT oder CoAP (RFC7252) in Verbindung gebracht, die speziell für Geräte konzipiert wurden, die bezüglich Rechenleistung und Stromverbrauch eingeschränkt sind. BEEP unterscheidet sich stark von diesen Machine-to-Machine- oder M2M-Protokollen, die beispielsweise bei der Hausautomatisierung für die Abfrage verteilter Sensoren eingesetzt werden.• BEEP ist ein Peer-to-Peer-Protokoll (P2P), dessen verbundene Knoten gleichberechtigt sind und in beide Richtungen (Full-Duplex) Informationen austauschen.
• MQTT und CoAP sind fertige Lösungen für einen speziellen Anwendungsfall, während BEEP ein Framework für die Erstellung eigener Anwendungsprotokolle ist. Beispielsweise kann mit BEEP die Funktionalität von MQTT nachgebaut werden.
• BEEP ist modular und erweiterbar.
• Ein starker Framing-Mechanismus ermöglicht das Senden großer Nachrichten ohne Blocking-Effekte.

Energieeffiziente Geräte, basierend auf ARM-Prozessoren und stromsparender Netzwerktechnik, ermöglichen einen größeren Funktionsumfang der verteilten Geräte. Die Folge ist ein deutlich umfangreicherer Kommunikationsbedarf zwischen den Knoten. Immer wenn ein existierendes Protokoll an seine Grenzen stößt, wird wohl ein neues erfunden. Schon heute ist die Protokolllandschaft ähnlich unübersichtlich wie die verwendeten Gerätetypen. BEEP geht einen anderen Weg, der das Potenzial hat, wertvolle Entwicklungsressourcen weg von weiteren Protokollen hin zu zukunftsorientierten Innovationen zu verschieben.

Profile und Kanäle

Dank des modularen Aufbaus von BEEP wird die komplette Kommunikation über eine einzige TCP-Verbindung abgewickelt. Profile definieren dabei die Funktionen, die ein Knoten zur Verfügung stellt. Um ein Profil eindeutig zu identifizieren, wird ein URI (Uniform Resource Identifier), zum Beispiel http://iana.org/beep/TLS, verwendet. Es muss sich dabei nicht um eine wirkliche Internetadresse handeln, jedoch sollte der Ersteller einer neuen ID der Eigentümer der verwendeten Domain sein, um die Eindeutigkeit zu gewährleisten.
Bevor eigene Profile entwickelt werden, lohnt es sich zu prüfen, ob nicht bereits existierende geeignet sind. Es gibt fertige Lösungen für XML-RPC (RFC3529), SOAP über BEEP (RFC4227), Tunnel (RFC3620), SASL/TLS (RFC3080) und mehr. Natürlich können Standardprofile auch zusammen mit eigenen verwendet werden. Zum Beispiel wird die Verbindung zu einem eigenen Profil durch SASL/TLS gesichert.
Bei einem BEEP-Kanal handelt es sich um eine Full-Duplex-Pipe, die von jedem der beiden Knoten erzeugt werden kann, egal welcher von ihnen die Verbindung aufgebaut hat. Nachrichten fließen gleichzeitig in beide Richtungen, wobei ihre Reihenfolge nicht verändert wird. Ein Kanal ist mit einem Profil verbunden. Es können jedoch, von beiden Seiten, beliebig neue Kanäle erzeugt werden, die unabhängig voneinander sind. Der Kanal 0 nimmt eine Sonderstellung ein und wird beim Aufbau einer BEEP-Session für Verwaltungszwecke, zum Beispiel dem Öffnen und Schließen neuer Kanäle, erzeugt. Wird der Kanal 0 geschlossen ist die BEEP-Session beendet. Abbildung 2 zeigt, wie Profile und Kanäle miteinander verbunden sind.

Abb. 2: Profile definieren Dienste, die über BEEP zur Verfügung gestellt werden; Kanäle ermöglichen eine Full-Duplex-Kommunikation, die wahlweise synchron oder asynchron erfolgt

Abb. 2: Profile definieren Dienste, die über BEEP zur Verfügung gestellt werden; Kanäle ermöglichen eine Full-Duplex-Kommunikation, die wahlweise synchron oder asynchron erfolgt

Open Source BEEP Cores

Es gibt verschiedene Open-Source-Implementierungen des BEEP Cores in C, Java und JavaScript. Die wohl umfangreichste C-Bibliothek stammt von der spanischen Firma ASPL, heißt Vortex, und bringt nicht nur den BEEP Core, sondern auch Erweiterungen durch Standardprofile und diverse Tools mit. Sprachanbindungen für Python (PyVortex), Free Pascal (BeepFp) und Lua (LuaVortex) erweitern den Anwendungsbereich. Eine JavaScript-Version von Vortex (jsVortex) steht ebenfalls zur Verfügung. Java-Entwickler können die auf Apache MINA basierende BEEP-Implementierung beep4j verwenden. Links zu weiteren Toolkits befinden sich im Internet auf der offiziellen BEEP-Seite.
Pakete für einige Linux-Distributionen und Microsoft Windows stehen auf der Vortex Seite zum Download bereit. Auf weiteren Plattformen wie Mac OS X oder Raspberry Pi, können die Quellen meist problemlos kompiliert und installiert werden. Vortex basiert auf AXL, einer XML-1.0-Implementierung, die installiert werden muss, bevor Vortex kompiliert werden kann. AXL stammt ebenfalls von ASPL und wird, obwohl ein Teil des Vortex-Projekts, als eigenständige Bibliothek zur Verfügung gestellt.
Für viele Anwendungen ist eine RPC-(Remote-Procedure-Call-)basierte Schnittstelle bereits ausreichend. Vortex bringt ein XML-RPC-Profil mit, das neben Standardtypen auch Strukturen und Listen unterstützt. Ein IDL-Compiler (Interface Definition Language) erstellt automatisch einen Server-Prozess und eine Client-Bibliothek, die den Zugriff auf den Server ermöglicht. Listing 1 zeigt ein Beispiel für eine IDL-Datei, die einen Datentyp und eine Funktion definiert, die den neuen Typ verwendet.

Listing 1
xml-rpc interface itest {
/* declare the struct Values */
struct Values {
int count;
double fraction;
boolean status;
}
/* declare the service using previous declaration */
Values get_struct (Values a, Values b) {
Values * result;
/* create the value to be returned */
result = itest_values_new (a->count + b->count,
a->fraction + b->fraction,
a->status || b->status);
/* return the result provided */
return result;
}
}

Geht’s noch einfacher?

Auf BEEP basierende Produkte vereinfachen die Entwicklung verteilter Anwendungen. Das ebenfalls als Open Source verfügbare Turbulence-Projekt ist ein auf Vortex basierender Application Server. In C oder Python entwickelte Module können mit Turbulence zusammengefasst und adressiert werden. Das ermöglicht ein Hosting von BEEP-basierten Diensten, ähnlich wie es im Internet für Web Services üblich ist.
TML/SIDEX von der Kieler Firma wobe-systems GmbH bietet eine Reihe von Lösungen für häufige Aufgaben bei der Entwicklung verteilter Systeme. Ebenfalls basierend auf Vortex wird BEEP genutzt, um Events, RPC, Streams und Load Balancing zur Verfügung zu stellen. Geschwindigkeit und asynchrone Kommunikation sind Schwerpunkte des Produkts. Zum Austausch von Daten wird ein typsicheres Datenformat (SIDEX) verwendet, dessen API die Datentypen für eine einfache Anwendung in möglichst vielen Programmiersprachen mitbringt. Aufgrund der Ähnlichkeiten mit anderen Austauschformaten wie JSON ist eine Konvertierung leicht möglich. Mit Python (Listing 2) oder PHP kann so über einen Webserver auf ein Backend zugegriffen werden, das aus einem oder mehreren Knoten besteht. Sprachanbindungen und die Unterstützung von verschiedenen Plattformen spielen eine wichtige Rolle. Bisher kann TML/SIDEX für Linux, Windows und Mac OS X verwendet werden. Aktuell ist eine Portierung auf Raspberry Pi in Arbeit. Für die Entwicklung stehen, neben dem C-API, Komponenten für Lazarus (Free Pascal) und RAD Studio sowie eine Python- und PHP-Erweiterung zur Verfügung.

Listing 2
def cmd43handler(tmlprofile, cmd):
"""return a list and a value"""
cmd.data['Result']['Value'] = 43
cmd.data['Result']['Test'] = [1, 2, 3, '没问题', 3.14]
def cmd44_progress_test(tmlprofile, cmd):
"""return multiple answers with progress"""
for p in range(0, 100, 10):
cmd.data['Result']['Progress'] = p
time.sleep(0.5)
cmd.progress = p
def main():
tmlcore = tml.core.TMLCore()
tmlcore.listener_binding = "127.0.0.1:12345"
cmdprofile = "http://www.tml-software.com/tml_rpc_server/test"
# register a command and profile
tmlcore.profiles.add_profile(cmdprofile)
tmlcore.profiles[cmdprofile].register_cmd(43, cmd43handler)
tmlcore.profiles[cmdprofile].register_cmd(44, cmd44_progress_test)
tmlcore.listener_enabled = True
run()
if __name__ == '__main__':
main()

Fazit und Ausblick

Durch immer stärker verteilte Anwendungen und steigende Anforderungen an die Kommunikation der Knoten im Internet stoßen existierende Client-/Server-Protokolle an ihre Grenzen. Es wird nach neuen Wegen gesucht, die vorhandenen Protokolle zu erweitern. Das ist nicht immer einfach, da die Kompatibilität zu älteren Version berücksichtigt werden muss. Die in Abbildung 3 dargestellte BEEP-Session zeigt, welche Möglichkeiten eine P2P-Kommunikation bieten muss, um die geforderte Geschwindigkeit und Stabilität verteilter Systeme in der Zukunft bereitstellen und leisten zu können. Auch wenn Netzwerke und Hardware immer leistungsfähiger werden, führen Virtualisierung und Cloud-Dienste zu unberechenbaren Verarbeitungszeiten. Anfragen, die sich gegenseitig blockieren, führen zu Fehlern und Performance-Problemen. Wie sich BEEP in Zukunft durchsetzt, bleibt abzuwarten. Die Funktionen, die BEEP heute schon bietet, werden sich mit Sicherheit in zukünftigen Lösungen wiederfinden.

Abb. 3: Ob Peer-to-Peer, Synchron, Asynchron, Multi-Reply oder Fehlerreporting, BEEP bietet alles, was ein Anwendungsprotokoll im IoT leisten muss; zukünftige Lösungen versprechen nur, was in BEEP bereits heute funktioniert

Abb. 3: Ob Peer-to-Peer, Synchron, Asynchron, Multi-Reply oder Fehlerreporting, BEEP bietet alles, was ein Anwendungsprotokoll im IoT leisten muss; zukünftige Lösungen versprechen nur, was in BEEP bereits heute funktioniert

Entwickler Magazin

Entwickler Magazin abonnierenDieser Artikel ist im Entwickler Magazin erschienen.

Natürlich können Sie das Entwickler Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Aufmacherbild: Building blocks via Shutterstock / Urheberrecht: hkeita

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -