Design Patterns: Entwurfs- und Architekturmuster für das Internet der Dinge
Mit dem Begriff Internet der Dinge (IoT) assoziiert man Milliarden vernetzter Geräte (Devices), wie z.B. Sensoren und Aktuatoren, die über hochgradig interoperable Standard-Internettechnologien miteinander kommunizieren und große Mengen an Daten produzieren. Doch was müssen System- oder Softwarearchitekten beachten, wenn sie IoT-Systeme planen und entwerfen? Und welche Entwurfs- und Architekturmuster passen zu dieser Kategorie von Systemen?
Anbieter zum Thema

Wobei helfen Entwurfsmuster?
Entwurfsmuster (engl. Design Patterns) sind ja grundsätzlich nichts Neues. Entwickler können ihr Erfahrungswissen mit Hilfe von Mustern konservieren, um für immer wiederkehrende Entwurfsprobleme einen Schatz an bewährten Lösungen parat zu haben. Ursprünglich kommen Muster noch nicht einmal aus der Softwareentwicklung. Populär wurden sie bereits gegen Ende der 1970er Jahre, nachdem der US-amerikanische Architekt, Systemtheoretiker und Philosoph Christopher Alexander gemeinsam mit weiteren Autoren seinen Musterkatalog „A Pattern Language“ [Alex77] veröffentlicht hat. In diesem Buch besprechen Alexander et al. etwa 270 Entwurfsmuster für die Gebäudearchitektur und die Städteplanung.
Nachdem 1994 das berühmte Werk „Design Patterns“ [Gamma94] der sogenannten „Gang of Four“ (kurz: GoF) erschienen war, wurden Entwurfsmuster auch in der Softwareentwicklung gebräuchlich und bekannt. Dieses Buch, das auch als die Bibel des objektorientierten Designs bezeichnet wird, zählt wohl mit zu den wichtigsten Werken der Software-Fachliteratur. Nur kurze Zeit später erschien mit „Pattern-Oriented Software Architecture{ [Buschmann96], häufig auch kurz als „POSA“ bezeichnet, ein weiterer Klassiker, der verbreitete Muster für Softwarearchitekturen diskutierte.
Mit dem Trend des Internet of Things stellen sich diesbezüglich natürlich zahlreiche Fragen. Beispielsweise, mit welchen typischen Entwurfsproblemen sind System- und Softwarearchitekten beim Konzipieren eines stark verteilten IoT-Systems, bestehend aus Tausenden von Devices, konfrontiert? Welche klassischen und bekannten Entwurfsmuster sind auch bei IoT-Systemen gut anwendbar? Wurden vielleicht sogar schon neue Muster entdeckt, die speziell für IoT-Systeme prädestiniert sind?
Die Schichtenarchitektur
Beginnen wir einmal mit einem Klassiker aus den Architekturmustern, der sogenannten Schichtenarchitektur (layered architecture). Dieses Architekturmuster ist sehr weit verbreitet. Das diesem Muster zu Grunde liegende Prinzip lautet Separation of Concerns (deutsch: Trennen nach Belangen). Viele existierende IT-Systeme besitzen eine Schichtenarchitektur, z.B. die häufig anzutreffende Variante mit den drei Schichten: Präsentationsschicht, Geschäftslogikschicht und Datenzugriffsschicht.
Für typische IoT-Systeme wurden zahlreiche sogenannte Referenzarchitekturen definiert, die ebenfalls geschichtet sind. Eine Referenzarchitektur ist ganz allgemein definiert als ein idealtypisches Referenzmodell (Muster) für eine Klasse von Architekturen. Sie stellen in der Architekturentwicklung die höchste Abstraktionsstufe dar.
Sehr populär im IoT-Umfeld ist die AIOTI HLA Referenzarchitektur [AIOTI18]. Dabei steht AIOTI für Alliance of Internet of Things Innovation, einer von der EU im Jahr 2015 gegründeten zwischenstaatlichen Organisation mit dem Ziel, den Dialog und die Interaktion zwischen den Akteuren beim Internet der Dinge in Europa zu stärken. HLA steht dabei für High Level Architecture. Jede Schicht der HLA, die im Bild 1 dargestellt ist, repräsentiert eine Gruppierung von Modulen, d.h. einen kohäsiven Satz von Services oder Entitäten.
Auf diese sehr abstrakte High-Level Referenzarchitektur lassen sich andere, bekannte IoT-Referenzarchitekturen sehr leicht abbilden. So findet man beispielsweise auch im ITU-T Y.2060 IoT Reference Model (ITU steht für die International Telecommunication Union) die drei Ebenen der AIOTI HLA.
Verlassen wir nun diese Flughöhe und steigen etwas weiter hinab zu den Architektur- und Entwurfsmustern, die vornehmlich innerhalb der Schichten zur Anwendung kommen können.
IoT-Systeme mit dem Kompositum hierarchisch strukturieren
Immer wenn Systeme sehr groß werden bietet sich eine hierarchische Strukturierung an. Mit 100.000 oder sogar viel mehr IoT-Devices lediglich „flach“ umzugehen, ohne diese in ein hierarchisches Systemkonzept einzuordnen, macht wenig Sinn. Das wäre in etwa vergleichbar mit dem kaum zu beherrschenden Chaos welches entstehen würde, wenn man auf dem PC alle seine Dateien direkt im Wurzelverzeichnis der Harddisk ablegen würde, ohne sie in Ordnern zu strukturieren.
Ein guter Ansatz um mit diesem Skalierbarkeitsproblem bei sehr großen Systemen umzugehen ist es, eine hierarchische Baumstruktur einzuführen, d.h. zusammengesetzte IoT-Geräte (Kompositen) zuzulassen, die ihrerseits aus mehreren IoT-Geräten bestehen können. Das entsprechende Entwurfsmuster ist das altbekannte Kompositum (Composite Pattern) aus [Gamma94], wie es für IoT-Systeme in der folgenden Abbildung 2 dargestellt ist.
Das Angenehme an diesem Pattern ist, dass man nun von der obersten Hierarchieebene aus nicht mehr zwingend jeden einzelnen Sensor oder Aktuator direkt ansprechen muss, sondern sich an die zusammengesetzten Devices (Composite Device) wenden kann, die die Daten der ihnen untergeordneten Geräte aggregiert haben. Zudem unterstützt eine solche Systemarchitektur auch die Umsetzung von REST (REpresentational State Transfer), dem Architekturstil des World Wide Web, der eine eindeutige Adressierbarkeit von hierarchisch strukturierten Ressourcen über eine URI fördert, wie in diesem Beispiel der Zugriff auf einen Temperatursensor in einem Raum eines Gebäudes:
https://api.monitoringsystem/building-monitoring/building/24/floor/2/room/10/temperature
Möchte ich nun alle Temperaturen von der 2. Etage des Gebäudes Nr. 24 abrufen, so sähe der entsprechende API-Aufruf wie folgt aus:
https://api.monitoringsystem/building-monitoring/building/24/floor/2/temperatures
Publish/Subscribe = Broker + Observer
Kommen wir nun zu einem Messaging-Pattern, welches beim Internet der Dinge eine signifikante Rolle spielt: Publish/Subscribe (kurz: „Pub/Sub“). Bei diesem Muster senden die Absender von Nachrichten, die sogenannten Publisher, diese Nachrichten nicht direkt an bestimmte Empfänger, die sogenannten Subscriber (dt.: Abonnenten). Stattdessen veröffentlichen die Publisher die in Klassen kategorisierten Nachrichten, ohne zu wissen, welche Abonnenten, falls überhaupt vorhanden, es geben kann.
Publish/Subscribe ist im Wesentlichen eine Fusion aus den beiden bekannten Entwurfsmustern Observer (Beobachter) [Gamma94] und Broker:
- Das Observer-Pattern kommt dort zur Anwendung, wo Änderungen an einem Objekt (dem sogenannten Subject) Änderungen an anderen Objekten – eben jene, die das Subject beobachten; die Observer – nach sich ziehen sollen. Dabei wird eine lose Kopplung zwischen dem Subject und seinen Beobachtern gefördert, indem die Beobachter sich für den Nachrichtenempfang am Subject jederzeit an- und abmelden können.
- Das Broker-Pattern (auch: Message-Broker) kann verwendet werden, um verteilte Softwaresysteme mit entkoppelten Komponenten zu strukturieren. Eine zentrale Komponente/Server, der sogenannte Broker, ist dabei für die Koordination der Kommunikation, wie z.B. Weiterleitungsanforderungen, sowie für die Übertragung von Nachrichten zuständig.
Ein sehr populäres Beispiel für Publish/Subscribe im IoT-Umfeld ist MQTT (Message Queue Telemetry Transport), ein sehr leichtgewichtiges M2M (Machine-to-Machine) Kommunikationsprotokoll. Das Abonnieren von Nachrichten geschieht bei MQTT Topic-basiert: Clients, die als Publisher arbeiten, senden dem Server (dem MQTT-Broker) nach Verbindungsaufbau Nachrichten mit einem bestimmten Topic, welches die Nachricht klassifiziert und hierarchisch einstuft. Beispiele:
Building/24/Floor/2/Room/10/TemperatureCar/Wheel/FrontRight/AirPressure
Andere Clients, die Subscriber, können diese Topics abonnieren, wobei der MQTT-Broker die empfangenen Nachrichten an die entsprechenden Abonnenten weiterleitet.
Der zentrale MQTT-Broker birgt natürlich einen Nachteil: Er ist ein sogenannter Single Point of Failure, d.h. fällt diese zentrale Komponente aus, kommt schlagartig die gesamte Kommunikation zum Erliegen. Einige Implementierungen eines anderem Publish/Subscribe-Protokolls, das insbesondere für anspruchsvolle Echtzeit-Anwendungen konzipierte OMG Data Distribution Service (DDS), verzichtet daher auf eine solche zentrale Broker-Instanz. Die Broker-Funktionalität ist bei DDS stattdessen verteilt realisiert und somit sehr ausfallsicher.
Centralized Hub & Spoke
Um mit einer kleinen, lokalen Anzahl an IoT-Devices über kurze Distanz zu kommunizieren, wird beim Hub & Spoke Pattern deren Datenverkehr über ein zentrales Gateway geleitet und gebündelt. Nur dieses Gateway ist direkt mit dem Internet verbunden, beispielsweise über den Mobilfunkstandard 4G/LTE, wogegen die IoT-Devices ausschließlich lokal mit dem Gateway kommunizieren.
Der Vorteil dieses Patterns ist, dass nur eine einzige Internet-Verbindung für n IoT-Devices gemanagt werden muss, und dass das Gateway zur Kommunikation mit den IoT-Devices in seinem nahen Umfeld einen anderen drahtlosen Kommunikationsstandard verwenden kann (beispielsweise ZigBee/IEEE 802.15.4), als für die Weitverkehrs-Verbindung mit dem Internet.
Darüber hinaus kann das Gateway auch für sogenanntes Edge Computing verwendet werden, d.h. die von diversen Sensoren erzeugten Messdaten werden – zumindest teilweise – an Ort und Stelle (vor)verarbeitet, bevor sie in die Cloud hochgeladen werden. Auch kann das Gateway die IoT-Daten mit weiteren Metadaten anreichern, wie z.B. mit geographischen Positionsangaben oder einem Zeitstempel.
Leader/Follower
Diskutieren wir als Letztes eines der zahlreich existierenden Nebenläufigkeits-Muster (Concurrency Pattern), das Leader/Follower Pattern.
In stark verteilten Systemen, in denen Ereignisse nicht-deterministisch auftreten können, kann auf Nebenläufigkeit in der effizienten Verarbeitung dieser Ereignisse häufig nicht verzichtet werden. Auf der anderen Seite kann ein unsachgemäßer Umgang mit Nebenläufigkeit aber auch zu vielen Problemen führen. Insbesondere die leistungsmindernden Faktoren, wie Kontextwechsel, Thread-Synchronisation, das Management der Cache-Kohärenz, aber auch vor allem die dynamische Allokation und Zuweisung von Speicherplatz verursachen erhebliche Laufzeit-Kosten auf konventionellen Multiprozessor-Betriebssystemen.
Das Leader/Follower-Pattern bietet ein Parallelitäts-Modell, mit dem in großer Zahl und nicht-deterministisch eintreffende Ereignisse (Events) entgegengenommen, und in effizienter Weise verarbeitenden Event-Handler-Threads zugeteilt werden können.
Stellen wir uns mal einen Taxistand bei Nacht vor. Der Taxistand ist der Thread Pool, an dem alle Taxifahrer (1..* Instanzen vom Typ Thread) schlafen, bis auf einen: der Fahrer des ersten Taxis: der Leader. Dieser Leader wartet aktiv auf einen Kunden.
Taucht ein Kunde am Taxistand auf, weckt der Leader einen anderen Taxifahrer auf, damit dieser der nächste Leader wird, und bedient die Anfrage seines Fahrgastes. Während dieser Fahrer nun den Kunden an die angegebene Adresse befördert, kann der neue Leader bei Bedarf sofort einen neuen Passagier bedienen. Wenn ein Fahrer fertig ist, fährt dieser sein Taxi zurück zum Bahnhof und schläft ein, wenn der Taxistand nicht leer ist. Andernfalls wird er sofort wieder zum Leader.
Die Vorteile dieses Musters sind:
- Es ist keine Kommunikation zwischen den Threads notwendig, d.h. keine Synchronisation oder Schutz gemeinsam genutzten Speichers (keine Sperren, keine Mutexe).
- Weitere ConcreteEventHandler können leicht hinzugefügt werden, ohne andere, bereits existierende ConcreteEventHandler zu modifizieren (Open-Closed Principle).
- Erhöhung der Performanz aufgrund der Vielzahl von bereitstehenden Threads zur Verarbeitung des Events.
Fazit: Viele bereits seit Jahrzehnten bekannte Muster auch bei IoT-Systemen haben nichts von ihrer Aktualität und Relevanz eingebüßt. Da man es bei IoT-Systemen typischerweise häufig mit sehr vielen weit verteilten Geräten (Sensoren und Aktuatoren) zu tun hat, nimmt wohl die Wichtigkeit von Mustern für Nebenläufigkeit (Concurrency), um mit einer großen Anzahl nicht-deterministischer Ereignisse effizient umgehen zu können, zu.
:quality(80)/images.vogel.de/vogelonline/bdb/1470500/1470531/original.jpg)
Software Design Patterns
Quellenverzeichnis
[AIOTI18] Alliance for Internet of Things Innovation. High Level Architecture (HLA) Release 4.0. URL: https://aioti.eu/wp-content/uploads/2018/06/AIOTI-HLA-R4.0.7.1-Final.pdf; zuletzt eingesehen am 21.10.2018
[Alex77] Christopher Alexander, Murray Silverstein, Sara Ishikawa. A Pattern Language: Towns, Buildings, Construction. Oxford University Press, 1977.
[Buschmann96] Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad, Michael Stal. Pattern-Oriented Software Architecture, Vol. 1: A System of Patterns. Wiley, 1996.
[Gamma94] Erich Gamma, Richard Helm, Ralph E. Johnson, John Vlissides. Design Patterns – Elements of Reusable Object-Oriented Software. Prentice Hall, 1994.
(Der Beitrag wurde mit freundlicher Genehmigung des Autors dem Tagungsband des Embedded Software Engineering Kongress 2018 entnommen.)
Autor
* Die thematischen Schwerpunkte bei Stephan Roth liegen in den Bereichen modellbasiertes Systems- und Software Engineering mit UML und SysML, Softwarearchitektur und -design sowie Clean Code Development. Zudem ist er Autor international verlegter Fachbücher.
Artikelfiles und Artikellinks
(ID:46128189)