Serie “Integrationsarchitektur” – Teil 2 Transport

Keine Kommentare

In dieser Blog Serie möchte ich einige der wichtigsten Themen und Fragestellungen rund um Enterprise Integration betrachten. Angefangen bei sehr abstrakten Fragestellungen führe ich zu immer konkreteren Beispielen, die dann mit unterschiedlichen ESB Technologien beispielhaft umgesetzt werden. Der heutige Artikel behandelt verschiedene Transportmechanismen innerhalb eines ESB.

Zu Teil 1 der Serie

Im letzten Artikel haben wir eine grobe Gesamtarchitektur für einen ESB entwickelt. Wir haben die folgenden drei Layer eingeführt:

  • Anwendungs-Layer (Enthält die anzubindenden Fremdanwendungen)
  • Transformations-Layer (Übernimmt die Transformation zwischen dem fremden und dem gemeinsamen Datenmodell und Transportkanal)
  • Vermittler-Layer (Übernimmt die Verteilung der Kommunikation und aggregiert komplexere Funktionen)

Wir haben außerdem festgestellt, dass zu einer funktionierenden Kommunikation immer ein Transportkanal sowie ein Datenformat erforderlich sind. Entsteht hier ein Bruch, ist eine Kommunikation nicht mehr möglich.
Heute möchte ich einige Anreize rund um das Thema „Transport“ geben, denn der Transport ist das Bindeglied zwischen all unseren Komponenten und damit allgegenwärtig. Zunächst suchen wir eine Format/Kanal-Kombination, die geeignet ist, die Kommunikation zwischen unseren Komponenten abzuwickeln. Rufen wir uns hierzu ein Beispiel ähnlich wie in Teil 1 in Erinnerung:

Abbildung 1 Beispiel

Abbildung 1 Beispiel

Eine Kommunikation geht von einer Anwendung (z.B. A) aus und führt zunächst zum jeweiligen Transformator (z.B. A <-> M). An dieser Stelle haben wir noch keinen Einfluss auf das Datenformat oder den Transportkanal, da beides in den meisten Fällen von der Anwendung vorgegeben wird. Wir benötigen ab hier jedoch eine Kombination, die geeignet ist, zwischen den Transformatoren und dem Vermittler eingesetzt zu werden. Da wir hier immer die gleiche Kombination verwenden möchten, suchen wir ein Format, mit dem sich möglichst vielfältige Datenstrukturen abbilden lassen. „CSV“, wie wir es im ersten Teil als Beispiel genutzt haben, scheidet hier schnell aus. Als gut geeignet haben sich hingegen XML oder JSON erwiesen. Mit diesen Formaten lassen sich auch wohldefinierte Schnittstellen erstellen, die wir zwischen unseren Layern dringend benötigen. Ein „Ordnungsrahmen“ wie z.B. SOAP oder REST/RAML kann an dieser Stelle helfen, die Entkopplung zu verbessern, ist aber für unser Beispiel überhaupt nicht erforderlich.

Beim Transportkanal wird es schwieriger. Auch „FTP“ aus unserem Teil-1-Beispiel eignet sich nicht sonderlich (auch wenn sich hier erstaunliche Muster umsetzen ließen). Die meisten Szenarien lassen sich hingegen mit einfachem HTTP oder via Messaging (JMS) umsetzen. Da sich mit JMS vielfältigere Szenarien umsetzen lassen und es mir gefällt, den Transport von einem separaten „Dienstleister“ abwickeln zu lassen, möchte ich an dieser Stelle etwas detaillierter auf Messaging eingehen.

Im Prinzip laufen beim Messaging alle Nachrichten über „Queues“ oder „Topics“. Eine Komponente, die eine Nachricht versenden möchte, legt diese in einer Queue oder einem Topic ab, wo sie von einem Empfänger entgegengenommen werden kann:

Abbildung 2 Messaging Grundprinzip

Abbildung 2 Messaging Grundprinzip

Der Unterschied zwischen Queue und Topic ist einfach zu erklären:

Queue – Mehrere Empfänger registrieren sich bei dieser Queue. Jede Nachricht wird jedoch nur genau einem Empfänger zugestellt. Ist kein Empfänger registriert, verbleibt die Nachricht solange in der Queue, bis sie abgeholt wird.

Abbildung 4 Topics

Abbildung 4 Topics

Topic – Mehrere Empfänger registrieren sich bei diesem Topic. Jede Nachricht wird an jeden dieser Empfänger zugestellt. Ist kein Empfänger registriert, geht die Nachricht ungelesen „verloren“. Dieses Verfahren ist bekannt als „Publish-Subscribe“.

Abbildung 3 Queues

Abbildung 3 Queues

Da die Nachrichten im Normalfall solange in einer Queue verbleiben, bis sie abgeholt werden, lässt sich hierüber ein Fire-And-Forget umsetzen, bei dem der Empfänger zum Zeitpunkt des Versandes nicht aktiv/online/verfügbar sein muss. Die Zustellung ist trotzdem garantiert, verschiedene Mechanismen stellen sicher, dass keine Nachricht ungesehen verloren gehen kann.
Da die Nachricht bei einer Queue nur an einen Empfänger zugestellt wird, auch wenn mehrere registriert sind, lässt sich hierüber ein automatisches Load-Balancing erreichen, ohne Gefahr zu laufen, Nachrichten mehrfach zu verarbeiten. Wir können beliebig viele Empfänger registrieren, jede Nachricht wird nur exakt einmal verarbeitet, und wir benötigen keinen zusätzlichen Load-Balancer mit großen Port-Ranges und separater Konfiguration. Das geht sogar so weit, dass ohne zusätzlichen Aufwand ein Load-Balancing zwischen mehreren Servern und zwischen jeder Komponente erreicht wird. Das bedeutet auch, dass wir extrem einfach in die Breite skalieren können. Ob nun 2, 20 oder 200 Empfänger die Nachrichten verarbeiten macht aus Transportsicht keinen Unterschied. Dies ermöglicht es auch, einzelne Empfänger unterbrechungsfrei auszutauschen (z.B. beim Deployment), da während der Offline-Zeit ein anderer Empfänger die Nachrichten verarbeitet:

Abbildung 5 Unterbrechungsfreier Austausch einer Komponente

Abbildung 5 Unterbrechungsfreier Austausch einer Komponente

Hinzu kommt, dass beim Messaging die Leistungsgeschwindigkeit zwischen Sender und Empfänger entkoppelt werden kann. Produziert der Sender schneller als der Empfänger verarbeiten kann, so werden die Nachrichten angestaut und nach und nach verarbeitet. Ein weiterer Vorteil ist die Tatsache, dass der technische Verbindungsaufbau zum JMS-Server immer vom Client ausgeht, auch wenn er als Empfänger auftritt. Dieser Vorteil ist für viele Unternehmen relevant, die restriktive Security-Vorgaben haben, die z.B. einen Verbindungsaufbau von außerhalb nicht zulassen.

Jede Queue und jedes Topic hat übrigens einen eindeutigen, frei wählbaren Namen. Geschickt vergeben sieht man von außen sofort, welche Daten über diese Queue transportiert werden, zu welchem Service in welcher Version sie gehören und welches Datenformat darin gesprochen wird. Außerdem lässt sich der Zugriff für jede Queue auf Benutzer bzw. Gruppen reduzieren.

Durch diese Eigenschaften stellt JMS in meinen Augen eine „Professionalisierung“ des gesamten Transports dar. Der Transport ist das Rückgrat des gesamten ESB und daher lohnt es sich, diesen aus der Verantwortung einzelner Komponenten zu nehmen und gemäß der Separation of Concerns in die Hände eines „Profis“ zu legen.

Bei mehreren Kunden konnte ich bisher jedoch eine große Skepsis gegenüber JMS erleben. Meist hatten diese Kunden bereits Erfahrungen mit Websphere MQ gesammelt. Geht es Ihnen genauso, möchte ich Ihnen eine andere Implementierung, zum Beispiel Apache ActiveMQ ans Herz legen. Ich bin sicher, Sie werden bald großen Gefallen am Messaging finden. Erste Beispiele finden Sie auch in den kommenden Teilen dieser Serie.

Zum Schluss möchte ich nochmal zum gemeinsamen Datenformat zurückkommen. Dieses Format wird im Allgemeinen auch als „CDM“ („Canonical Data Model“ oder „Common Data Model“) bezeichnet. Lange Zeit war dessen Ziel, ein unternehmensweit einheitliches Datenmodell zu etablieren, so dass alle Anwendungen exakt die gleiche Vorstellung haben, wie z.B. ein „Kunde“-Objekt aussieht.

Ein Traumzustand für jeden ESB! Baut man allerdings nicht gerade einen ESB für ein extrem junges Unternehmen, so bestehen kaum reelle Chancen, dieses Ziel zu erreichen. Der Aufwand, ein womöglich komplexes Datenmodell zwischen mehreren Unternehmensbereichen abzustimmen, in dem alle Informationen aller Beteiligten enthalten sind, ist enorm. Es hat sich daher als guten Mittelweg herausgestellt, gemeinsame Datenmodelle nur innerhalb einer Geschäftsdomäne zu etablieren (hier besteht oft bereits ein gemeinsames Verständnis) und nur Teile wiederzuverwenden. Um trotzdem ein gewisses Maß an Wiederverwendbarkeit zu erreichen, empfiehlt es sich, alle Elemente z.B. eines Schemas strikt zu versionieren und hierüber eine Entkopplung zu erzielen, so müssen Änderungen nicht sofort an alle Beteiligten ausgerollt werden. Es ist außerdem hilfreich, einen „Verantwortlichen“ für die Definition des CDM festzulegen, der den Lebenszyklus des Datenmodells „betreut“.

Wie geht es nun weiter? Im nächsten Artikel werden wir uns einige JMS Implementierungen anschauen, und Werkzeuge vorstellen, die bei der Arbeit mit Messaging erforderlich und hilfreich sind.

Zu Teil 3 der Serie

Tobias Schaber

Neben seinem Schwerpunkt „Verteilte Systeme“ beschäftigt sich Tobias Schaber mit den Themen DevOps und Infrastructure-As-Code und automatisiert zum Beispiel die Bereitstellung von komplexen Systemen wie OpenStack oder Elasticsearch-Clustern.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.