Talk notes
This commit is contained in:
265
notes/NOTES.md
Normal file
265
notes/NOTES.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# Millionen langlebiger TCP-Verbindungen – Herausforderungen und Lösungen bei Update-Prozessen
|
||||
|
||||
Ihr wollt in euren Urlaub starten, seid mit gepackten Koffern am Bahnhof. Beim Warten auf den verspäteten Zug habt ihr jede
|
||||
Menge Zeit zum überlegen. Ihr fragt euch: "Ist der Herd wirklich abgeschaltet?". Anders als in früheren Urlauben habt ihr aber
|
||||
einen smarten Herd daheim. Ihr öffnet eure App, stellt fest, dass alles in Ordnung ist, und könnt beruhigt in Urlaub starten.
|
||||
|
||||
IoT (also "Internet of Things") beschreibt genau diese Art von Geräten. Mein Name ist Bene. Ich bin Softwareentwickler mit Fokus
|
||||
auf Softwarearchitektur bei Scandio. Wir bei Scandio entwickeln für unsere Kunden maßgeschneiderte intelligente und kreative
|
||||
Softwarelösungen. Wir haben dabei einen Schwerpunkt unter anderem im Bereich "Internet of Things".
|
||||
|
||||
Ein Projekt aus diesem Bereich will ich heute vorstellen. Dabei geht es darum, wie die IoT-Geräte unseres Kunden mit
|
||||
verschiedenen Backends kommunizieren und um die Herausforderungen bei der Aktualisierung des Systems, das zwischen den Geräten
|
||||
und den Backends liegt.
|
||||
|
||||
## Inhalt
|
||||
|
||||
Ein kurzer Überblick über den Vortrag: Nach dem Projektsetup (also Hintergrund, Motivation und Ziel des Projekts) beschreibe ich
|
||||
euch die Problemstellung etwas genauer und dann natürlich auch die Lösungen, also: wie sieht die Architektur des Systems jetzt
|
||||
ab, was genau passiert, wenn das System Updates bekommt, und zum Schluss noch: was wären unsere Wunschträume für die
|
||||
Architektur, wenn Zeit und Geld keine Rolle spielen würde oder wir ganz von vorne anfangen würden.
|
||||
|
||||
Eine organisatorische Bemerkung: wenn während des Vortrags Fragen aufkommen, stellt sie gerne sofort und ich werde sie so gut
|
||||
wie möglich beantworten.
|
||||
|
||||
## Über Scandio
|
||||
|
||||
Noch kurz ein paar Worte über Scandio: Vorhin habe ich ja schon gesagt, dass wir individuelle Software entwickeln, wobei wir
|
||||
neben IoT noch Stärken in den Bereichen Cloud und Systems Engineering, DevOps und Fullstack-Web-Entwicklung haben. Daneben
|
||||
unterstützen wir mit agilen Coaches und Beratern dabei, Prozesse zu optimieren. Insbesondere helfen wir als Atlassian Platinum
|
||||
Solution Partner unseren Kunden bei ihrer agilen Transformation.
|
||||
|
||||
## Projektsetup
|
||||
|
||||
[5] Das Projekt, von dem ich heute rede, hat den Namen "Heimdall".
|
||||
|
||||
Heimdall ist in der nordischen Mythologie der Wächter der Götterbrücke Bifröst (das ist der Regenbogen im Bild) und Heimdall hat
|
||||
außergewöhnliche Wahrnehmungsfähigkeiten. Hier im Bild ist das durch das Hören symbolisiert. Genauso wie Heimdall die Verbindung
|
||||
zwischen den Welten überwacht, fungiert unser Heimdall-System als ein Gateway, das die Brücke zwischen einer Vielzahl von
|
||||
IoT-Geräten und verschiedenen Backend-Systemen bildet. Ähnlich der mythischen Figur hat unser Heimdall die Aufgabe, die
|
||||
Sicherheit, Stabilität und Effizienz dieser Verbindungen zu gewährleisten.
|
||||
|
||||
Heimdall wird seit 2018 entwickelt und hat ein vollständig extern entwickeltes und verwaltetes System abgelöst. Bei diesem alten
|
||||
System hatte unser Kunde keinen Zugriff auf den Source Code oder Entwicklungsdetails. Daher wurde die Entscheidung für eine
|
||||
Neuentwicklung getroffen. Die fehlenden Informationen über das alte System gingen sogar so weit, dass wir bei der Migration zu
|
||||
unserem neuen System regelmäßig das alte System überlastet haben, da wir einfach keine Informationen bekommen konnten, welche
|
||||
Last das alte System aushält. Mit diesem Lock-In-Effekt war unser Kunde verständlicherweise unzufrieden und hat uns beauftragt,
|
||||
Heimdall neu zu entwickeln.
|
||||
|
||||
Ich will hier einmal schematisch zeigen, welche Aufgabe Heimdall hat. Eure smarte Herdplatte von vorhin muss regelmäßig an das
|
||||
Herdplattenstatusbackend die Information senden, welche Herdplatten auf welcher Stufe angeschaltet sind. Gleichzeitig tauscht
|
||||
das smarte Heizungsthermostat eures Nachbarn Nachrichten mit einem Backend aus, um herauszufinden, ob die Heizung nach oben oder
|
||||
unter geregelt werden sollte, und die smarte Dunstabzugshaube eurer Tante meldet an das entsprechende Backend, dass die Filter
|
||||
mal wieder eine Reinigung bräuchten. Heimdall sitzt zwischen den Geräten und den Backends und sorgt dafür, dass die richtigen
|
||||
Nachrichten das richtige Backend erreichen, und dass umgekehrt auch Nachrichten in die Gegenrichtung versendet werden können:
|
||||
beispielsweise kann das Herdplattenbackend die Herdplatte anweisen, sich abzuschalten. Die Geräte halten dazu eine Verbindung zu
|
||||
Heimdall aufrecht. Über diese Verbindung werden die Nachrichten dann ausgetauscht.
|
||||
|
||||
## Problemstellung
|
||||
|
||||
[10] Das wichtigste Qualitätsziel bei Heimdall ist, dass diese Verbindungen zwischen Gerät und Heimdall so selten wie möglich
|
||||
unterbrochen werden. Das hat zwei Gründe: Zum einen kann ich als Nutzer nicht sehen, auf welcher Stufe mein Herd gerade kocht,
|
||||
wenn der Herd nicht mit Heimdall verbunden ist. Zum anderen finden einige Prozesse nach jeder Neuverbindung statt. Das kann
|
||||
potenziell zu Überlastung von Heimdall oder den Backends führen, wenn die Neuverbindungen zu häufig stattfinden.
|
||||
|
||||
Ein Szenario gibt es aber, in dem Verbindungen auf keinen Fall gehalten werden können: nämlich wenn der Server, mit dem die
|
||||
Hausgeräte verbunden sind, ein Update bekommt und daher ersetzt werden muss. Deswegen ist eins der größten Ziele bei der
|
||||
Entwicklung der Architektur von Heimdall, dass solche Neustarts bei den meisten Konfigurationsänderungen des Systems nicht
|
||||
notwendig sind, sondern die Konfigurationsänderung am Live-System durchgeführt werden können.
|
||||
|
||||
## Lösungen
|
||||
|
||||
Diesem Prinzip, dass Konfigurationsänderungen ohne Neustarts möglich sein sollen, werden wir bei der Betrachtung der
|
||||
Heimdall-Architektur noch öfter begegnen. Wir schauen uns jetzt mal an, wie Heimdall aufgebaut ist.
|
||||
|
||||
Das Kernstück von Heimdall ist der sogenannte "Web Socket Manager", kurz WSM. Eure Herdplatte kann über euer heimisches WLAN mit
|
||||
Idem Internet kommunizieren. Nachdem die Firmware der Herdplatte gestartet und die Verbindung mit dem Internet hergestellt
|
||||
wurde, versucht die Herdplatte eine Websocket-Verbindung zum WSM zu öffnen. Dabei handelt es sich um eine dauerhafte Verbindung,
|
||||
über die zu beliebigen Zeiten Nachrichten in beide Richtungen entlang der Verbindung geschickt werden können. Die Verbindung
|
||||
wird so lange wie möglich aufrecht erhalten. Es gibt im Wesentlichen vier Gründe für den Abbruch der Verbindung: Das Gerät wurde
|
||||
abgeschaltet, die Netzwerkverbindung zwischen Gerät und WSM wurde unterbrochen, der WSM wurde beendet oder der WSM hat die
|
||||
Verbindung beendet. Im letzten Fall teilt also der WSM dem Gerät mit, dass über die Verbindung keine Daten mehr entgegengenommen
|
||||
oder verschickt werden können, ohne dass WSM oder Gerät beendet wurden. Gehen wir also mal davon aus, dass die Verbindung
|
||||
geöffnet ist und die Herdplatte mit dem WSM kommuniziert. Dann leitet der WSM die Nachrichten des Geräts an ein Backend weiter
|
||||
und umgekehrt werden Nachrichten vom Backend an das Gerät zurückgeleitet. Wenn es nur ein Gerät und nur ein Backend geben würde,
|
||||
wäre ich jetzt fertig mit der Präsentation. Das ist aber natürlich nicht alles.
|
||||
|
||||
[15] In Wirklichkeit gibt es ja außer eurer Herdplatte auch noch den Thermostat eures Nachbarn, die Dunstabzugshaube eurer Tante
|
||||
und noch jede Menge andere Geräte, die mit den Backend-Systemen kommunizieren sollen. Unser Deployment ist in vier verschiedene
|
||||
Regionen aufgeteilt, und in der größten Region, der Region Europa, haben wir aktuell etwa 2,5 Millionen Geräte, die zur gleichen
|
||||
Zeit mit Heimdall verbunden sind. Deshalb gibt es auch mehrere WSM-Pods, also mehrere Instanzen des WSM. Zum einen wird dadurch
|
||||
die Skalierbarkeit des Systems verbessert, und zum anderen verlieren im Falle eines Crashs nicht alle Geräte gleichzeitig die
|
||||
Verbindung. Vor diesen Instanzen liegt ein Load Balancer, der versucht, die Verbindungslast möglichst gleichmäßig zu verteilen,
|
||||
um Rechenressourcen möglichst effizient nutzen zu können. Der Load Balancer routet die Verbindungen von den Geräten zum WSM im
|
||||
Round-Robin-Algorithmus, also: eure Herdplatte verbindet sich zuerst und wird an die erste Instanz geroutet, danach kommt die
|
||||
smarte Glühbirne eures Freunds, die wird dann an die zweite Instanz geroutet, und nach der letzten Instanz beginnt das Spiel von
|
||||
vorne. Bei synchronen Aufrufen an das Backend kommt die Antwort an die richtige WSM-Instanz zurück. Allerdings führen synchrone
|
||||
Aufrufe zu zwei Nachteilen: zum einen muss der WSM auf die Antwort des Backends warten und so lange die Verbindung zum Backend
|
||||
offen halten. Wenn sehr viele Nachrichten auf einmal verschickt werden und das Backend langsam arbeitet, kann das zur
|
||||
Überlastung des WSM führen. Ein zweiter Nachteil von synchronen Aufrufen ist die stärkere Kopplung: die Verarbeitung der
|
||||
Nachricht schlägt nämlich fehl, wenn das Backend oder weiter innen liegende Systeme bei der Verarbeitung der Nachricht
|
||||
scheitern. Da sind asynchrone Aufrufe die bessere Lösung. Das heißt, dass entweder das Backend die Nachricht entgegennimmt und
|
||||
erst im Nachgang verarbeitet, oder dass der WSM die Nachricht an einen hochverfügbaren Message Broker schickt und die Backends
|
||||
die Nachricht in ihrer Geschwindigkeit zu einer späteren Zeit konsumieren können. Egal, für welche Lösung man sich hier
|
||||
entscheidet: das Backend muss eine Nachricht zurück an das Gerät senden, weiß aber noch nicht, mit welcher WSM-Instanz das Gerät
|
||||
verbunden ist. Übrigens hätten wir das selbe Problem auch ganz ohne synchrone Aufrufe: sagen wir mal, euer Nachbar möchte seiner
|
||||
Heizung mitteilen, dass sie die Temperatur in der Wohnung auf 22 Grad hochregeln soll, weil er jetzt auf dem Heimweg ist. Dann
|
||||
muss das Heizungsbackend eine Nachricht an den Thermostat schicken. Wenn das Backend versucht, die Nachricht über eine zufällige
|
||||
Instanz des WSM zu schicken, ist die Chance nicht sehr hoch, dass der Thermostat gerade mit dieser Instanz verbunden ist.
|
||||
|
||||
Hier kommen der Forwarding-Service (kurz FORS) und eine Adress-Datenbank ins Spiel. Jeder WSM-Pod schreibt nach einer geöffneten
|
||||
Verbindung mit einem Gerät die Geräte-ID zusammen mit der eigenen Adresse in die Adress-Datenbank. Der FORS fragt jetzt für ein
|
||||
Gerät die richtige Adresse ab und kann Nachrichten vom Backend an die richtige WSM-Instanz weiterleiten. Konkret schaut der
|
||||
Ablauf also so aus: Gerät 1 baut eine Websocket-Verbindung zu WSM-Pod 1 auf. In der Folge teilt WSM-Pod 1 der Adress-Datenbank
|
||||
mit: Gerät 1 ist mit dem Pod verbunden, der Adresse 1 besitzt. An der Kommunikation vom Gerät zum Backend hat sich nichts
|
||||
geändert. Wenn jetzt aber das Backend eine Nachricht an das Gerät senden möchte, dann wird die Nachricht an unseren
|
||||
Forwarding-Service geschickt. Der Forwarding-Service fragt die konkrete Adresse des richtigen WSM-Pods bei der Adress-Datenbank
|
||||
an und leitet die Nachricht entsprechend weiter. Dann ist die Nachricht beim richtigen WSM gelandet und kann an das Gerät über
|
||||
die Websocket-Verbindung geschickt werden.
|
||||
|
||||
[20] Dazu kommt, dass es in Wirklichkeit nicht nur ein Backend gibt. Ein Message Mapping kann vom WSM genutzt werden, um zu
|
||||
entscheiden, an welches Backend ein konkreter Nachrichtentyp mit einer konkreten Version gesendet werden soll. Der Ablauf hier
|
||||
ist also: Das Gerät (der Einfachheit halber habe ich in diesem Bild nur noch ein Gerät) schickt die Nachricht mit dem Typ
|
||||
"/foo/config" und der Version 1 an den WSM. Der WSM findet mit Hilfe des Message Mappings heraus, dass Backend 1 für die
|
||||
Verarbeitung der entsprechenden Nachrichten verantwortlich ist und leitet die Nachricht entsprechend weiter. Wir sind also wie
|
||||
ein Postunternehmen dafür zuständig, dass die richtigen Nachrichten an den richtigen Empfänger gelangen, aber nicht dafür, dass
|
||||
die Nachrichten inhaltlich auch sinnvoll sind. Es findet also bei Heimdall keinerlei Validierung der Nachrichten statt. Das
|
||||
Message Mapping ändert sich regelmäßig. Deshalb ist es wichtig, dass eine Rekonfiguration ohne Neustart der WSM-Pods möglich
|
||||
ist, da sonst ja Verbindungen gekappt werden müssten.
|
||||
|
||||
Der WSM hat noch diverse andere Aufgaben:
|
||||
|
||||
* Er führt den TLS-Handshake durch. Das heißt: alle Informationen, die zwischen Gerät und WSM ausgetauscht werden, werden
|
||||
verschlüsselt ausgetauscht. Dabei muss sich sowohl der Server, also der WSM, beim Gerät authentifizieren, als auch das Gerät
|
||||
nachweisen, dass es sich tatsächlich um ein Gerät unseres Kunden handelt. Die Authentifizierungen finden statt, indem
|
||||
überprüft wird, dass Gerät und WSM beide Zertifikate besitzen, die von einer vertrauenswürdigen Entität, also einer
|
||||
Certificate Authority (kurz CA) des Kunden signiert wurden.
|
||||
* Bei der Validierung des Zertifikats, das das Gerät ausweist, gibt es noch ein paar Details zu beachten. Nämlich gibt es etwa
|
||||
10 verschiedene ausstellende CAs, also Certificate Authorities, denen der WSM vertrauen soll. Manche dieser CAs haben
|
||||
Zertifikate ausgestellt, die inzwischen abgelaufen sind und die daher von einer Standard-Validierung nicht akzeptiert werden
|
||||
würden. Das Problem dabei: für Firmware-Updates müssen auch Nachrichten über Heimdall ausgetauscht werden, und die
|
||||
entsprechenden Geräte-Zertifikate können ohne ein Firmware-Update nicht aktualisiert werden. Deshalb muss Heimdall auf die
|
||||
Validierung des Gültigkeitszeitraums für die entsprechenden CAs verzichten.
|
||||
* Manche Geräte-Zertifikate sollen außerdem sofort abgelehnt werden, weil die entsprechenden Geräte defekt sind. Das wird über
|
||||
eine Datenbank mit blockierten Zertifikaten geregelt. Für das Blockieren eines Zertifikats ist wie beim Message Mapping kein
|
||||
Neustart des WSM notwendig, sodass auch hier Neuverbindungen vermieden werden.
|
||||
* Noch einmal andere Geräte sind in einem Quarantäne-Status. Für diese Geräte dürfen nur bestimmte Nachrichten versendet und
|
||||
empfangen werden, beispielsweise wieder Nachrichten im Zusammenhang mit Firmware-Updates. Wie die blockierten Zertifikate wird
|
||||
das über eine eigene Datenbank konfiguriert und benötigt keinen WSM-Neustart.
|
||||
* Dann muss der WSM noch den Websocket-Upgrade durchführen (dazu sage ich später noch mehr).
|
||||
* Schließlich gibt es noch einen Corporate Handshake, der vom Protokoll unseres Kunden vorgesehen ist. Bevor dieser Handshake
|
||||
abgeschlossen ist, dürfen keine anderen Nachrichten in beide Richtungen gesendet oder weitergeleitet werden.
|
||||
|
||||
[25] Hier ist noch einmal eine Zusammenfassung des gesamten Heimdall-Systems, soweit es für den Vortrag relevant ist. Die
|
||||
Grundidee ist also, dass der WSM so selten wie möglich neugestartet werden muss. Das erreichen wir, indem Konfiguration, die
|
||||
sich regelmäßig ändern könnte, externalisiert wird und ohne Neustarts geändert werden kann. Das sieht man in diesem Bild durch
|
||||
das Message Mapping und die beiden Datenbanken zum Blockieren von Zertifikaten und für den Quarantäne-Status.
|
||||
|
||||
Was passiert jetzt aber, wenn der WSM doch einmal neugestartet werden muss oder abstürzt? Wenn ein WSM-Pod kontrolliert beendet
|
||||
wird, werden die Verbindungen zu den entsprechenden Geräten nacheinander beendet. Dann verbinden sich die Geräte mit anderen
|
||||
Instanzen neu. Aktuell dauert dieser Prozess in unserer größten Stage mit etwa 2,5 Millionen Geräten knapp 3 Stunden. Da wir ja
|
||||
Round-Robin für das Load Balancing nutzen, hat der Ersatz-Pod, der hier gestartet wurde, danach deutlich weniger offene
|
||||
Verbindungen als die alten Pods. In der Praxis führt das nicht zu Problemen, denn die Last ist bei neuen Verbindungen mit
|
||||
Abstand am höchsten.
|
||||
|
||||
Falls ein Pod (beispielsweise aufgrund eines Bugs) unkontrolliert beendet wird, versuchen sich alle Geräte auf einmal neu zu
|
||||
verbinden. Das würde zur Überlastung des Systems führen, daher gibt es einen Rate Limiter, der dafür sorgt, dass sich Geräte
|
||||
nicht zu schnell wieder verbinden können. Natürlich ist das ein ungünstiger Zustand, da die Funktionalität der noch nicht wieder
|
||||
verbundenen Geräte eine ganze Weile eingeschränkt sein kann.
|
||||
|
||||
Jetzt kommen wir mal zum geplanten Fall: eine neue WSM-Version soll deployed werden. Das Deployment läuft dann so ab: In einem
|
||||
ersten Schritt werden 1/3 der Instanzen als Canary-Deployment durch Instanzen der neuen Version ersetzt. Diese neue Version
|
||||
läuft parallel zu der alten für eine Woche, bevor auch die übrigen Instanzen ersetzt werden. So können Fehler frühzeitig erkannt
|
||||
werden.
|
||||
|
||||
[30] Das bedeutet übrigens nicht, dass nach dem Canary-Deployment 1/3 der Verbindungen auf der neuen Version stattfinden. Die
|
||||
Wahrheit ist hier etwas komplizierter: die Geräte, die sich nach dem Abschalten mancher der alten Instanzen neu verbinden,
|
||||
verbinden sich ja genauso häufig mit jeder der Canary-Instanzen wie mit jeder der alten Stable-Instanzen. In dem 7-Tage-Zeitraum
|
||||
gleichen sich die Anzahl der verbundenen Geräte dann etwas aus, weil Geräte regelmäßig auch aus anderen Gründen die Verbindung
|
||||
verlieren und sich neu verbinden. Nach einer Woche werden die übrigen 2/3 der Instanzen ersetzt und wie vorhin haben dann die
|
||||
zuerst deployeten Canary-Instanzen mehr offene Verbindungen als die zuletzt deployeten. Wie gesagt führt das allerdings in der
|
||||
Praxis zu keinen Problemen und gleicht sich auf Dauer von selbst aus.
|
||||
|
||||
Jetzt habt ihr gesehen, wie das System tatsächlich aussieht. Natürlich haben wir in den gut 5 Jahren, in denen das Projekt
|
||||
existiert, auch dazugelernt und würden einige Dinge anders gestalten. Am Anfang des Vortrags habe ich ja schon gesagt, dass das
|
||||
Ziel wäre, den WSM so selten wie möglich updaten zu müssen. Dafür ist es hilfreich, wenn der WSM so wenige Aufgaben wie möglich
|
||||
bekommt. In einer idealen Welt sollte daher der WSM der kleinste Service im gesamten System sein. Die Realität ist: der WSM ist
|
||||
der mit Abstand größte Service des Heimdall-Systems.
|
||||
|
||||
Woran liegt das? Aktuell hat der WSM einige Aufgaben:
|
||||
|
||||
* TLS und alles, was dazugehört: die Terminierung der TLS-Verbindung, die Validierung der Geräte-Zertifikate, die Ausnahmen zur
|
||||
Validierung der Zertifikate und das Blocklisting von Zertifikaten.
|
||||
* Der Websocket-Upgrade, also die Entgegennahme der initialen HTTP-Verbindung und der Wechsel zum Websocket-Protokoll
|
||||
* Der Corporate Handshake, der zu Beginn jeder Verbindung stattfinden muss
|
||||
* Das Message Routing an die Backends inklusive Offenhalten der Verbindungen und Warten auf Antworten
|
||||
* Die Quarantäne-Logik
|
||||
* Einige andere Workarounds, die im WSM diverse Spezialfälle abhandeln
|
||||
|
||||
Um also den WSM möiglichst klein zu bekommen, müssen möglichst viele dieser Aufgaben ausgelagert werden. Oder umgekehrt: die
|
||||
Aufgaben, die unbedingt notwendig zum Halten der Verbindung sind, sollten aus dem WSM extrahiert werden.
|
||||
|
||||
[35] Bevor ich einen Vorschlag vorstelle, wie wir das erreichen könnten, will ich noch einmal ein bisschen detaillierter
|
||||
erklären, wie das Websocket-Protokoll funktioniert. Das Gerät eröffnet zu Beginn eine TCP-Verbindung zum WSM. Es ist nicht
|
||||
besonders wichtig zu wissen, was TCP genau macht, sondern nur, dass man bei einer TCP-Verbindung Daten in beide Richtungen
|
||||
verschicken kann und dass die TCP-Verbindung jederzeit auf beiden Seiten geschlossen werden kann. Nach Öffnung der
|
||||
zugrundeliegenden Verbindung findet der TLS-Handshake mit Verschlüsselung und Authentifizierung statt. Ab diesem Zeitpunkt
|
||||
verläuft die Kommunikation verschlüsselt und der WSM kennt ein Zertifikat, das das jeweilige Gerät ausweist. Als nächstes wird
|
||||
vom Gerät der Websocket-Endpunkt aufgerufen und der WSM wechselt das Protokoll zum Websocket-Protokoll. Ab hier können beliebige
|
||||
Daten im Websocket-Protokoll zwischen Gerät und WSM hin und her geschickt werden. Dann passiert der Corporate Handshake und
|
||||
schließlich der Austausch von beliebigen anderen Nachrichten, beispielsweise über den Status der Geräte. Die Verbindung
|
||||
inklusive TLS-Terminierung muss von einem einzigen Server gehalten werden, wenn wir nicht komische Nichtstandard-Dinge mit
|
||||
Verschlüsselung tun wollen, was aus Security-Gesichtspunkten natürlich keine gute Idee ist. Allerdings könnte die gesamte
|
||||
Kommunikation, die nach der Entschlüsselung der Nachrichten, also unterhalb der ersten gestrichelten Linie, stattfindet,
|
||||
außerhalb des Services stattfinden, der die Verbindung hält.
|
||||
|
||||
Hier wäre daher unser Vorschlag, um die Verbindungen noch länger halten zu können. Vor die übrigen Systeme wird ein Service
|
||||
gesetzt, den ich hier "Connection Holder" genannt habe und der nur dafür zuständig ist, die TCP-Verbindung zu den Geräten zu
|
||||
halten, die TLS-Verschlüsselung zu terminieren und zu Validieren, dass die Geräte-Zertifikate von einem bekannten Issuer
|
||||
ausgestellt wurden. Nach der TLS-Terminierung wird die TCP-Verbindung einfach an das Äquivalent des jetzigen WSMs
|
||||
weitergetunnelt. Wenn die WSM-Instanz beendet wird, kann der Tunnel an eine andere WSM-Instanz weitergeroutet werden, ohne die
|
||||
Verbindung zum Gerät abzubrechen. Damit der WSM Zertifikatslogik wie Blocklisting durchführen kann, muss zu Beginn des
|
||||
Verbindungsaufbaus zwischen Connection Holder und WSM das validierte Geräte-Zertifikat mitgeschickt werden. Außerdem müssen die
|
||||
Verbindungen eine eindeutige ID bekommen, sodass die WSM-Instanzen beispielsweise persistieren können, ob für eine gegebene
|
||||
Verbindung bereits der Corporate Handshake durchgeführt wurde. Natürlich könnten auch andere Aufgaben aus dem WSM ausgelagert
|
||||
werden, hier mal exemplarisch das Message Routing inklusive Warten auf die Antwort des Backends.
|
||||
|
||||
[40] Schauen wir uns das ganze in der Laufzeitsicht etwas genauer an. Das Gerät öffnet also eine TCP-Verbindung inklusive TLS
|
||||
zum Connection Holder. Diese Verbindung soll jetzt möglichst lange bestehen bleiben. Der Connection Holder erstellt eine
|
||||
eindeutige Verbindungs-ID, die der WSM später nutzen kann, um Verbindungen zu identifizieren und ihren Status zu vergleichen.
|
||||
Der Connection Holder sucht sich per Load Balancing eine WSM-Instanz, zu der er eine TCP-Verbindung öffnet. Das Gerät öffnet
|
||||
eine Websocket-Verbindung zum Connection Holder, der wiederum eine Websocket-Verbindung zum WSM öffnet. Dort wird überprüft, ob
|
||||
das validierte Geräte-Zertifikat akzeptiert werden soll und gegebenenfalls kann der WSM an dieser Stelle die Verbindung sofort
|
||||
beenden. Andernfalls wird die Connection-ID persistiert, mit dem Status "hier existiert eine Verbindung, für die aber noch kein
|
||||
Corporate Handshake durchgeführt wurde". Die Antworten "101 Switching Protocols" sorgen dafür, dass die jeweiligen
|
||||
Websocket-Verbindungen geöffnet sind. Alle weiteren Nachrichten werden vom Connection Holder zwischen Gerät und WSM
|
||||
weitergetunnelt. Jetzt kann der WSM also wie gehabt den Corporate Handshake durchführen, würde danach auch wieder einen Status
|
||||
für die jeweilige Verbindung persistieren, und könnte dann Nachrichten wie zuvor weiterleiten. Wenn jetzt die TCP-Verbindung vom
|
||||
WSM beendet wird, öffnet der Connection Holder eine TCP-Verbindung zu einer anderen WSM-Instanz und versucht, auch dorthin eine
|
||||
Websocket-Verbindung zu etablieren. Durch die persistierte Connection-ID erkennt die zweite WSM-Instanz, dass der Corporate
|
||||
Handshake bereits durchgeführt wurde und behandelt die Verbindung entsprechend. Ab diesem Zeitpunkt werden Nachrichten an die
|
||||
zweite WSM-Instanz weitergetunnelt. Das Gerät merkt davon nichts.
|
||||
|
||||
Von innen betrachtet würde der Connection Holder so aussehen: Außen liegt der TCP Connector, der die TCP-Verbindung zum Gerät
|
||||
entgegennimmt und die Connection-ID erstellt. Dann kommt ein Filter, der für die TLS-Terminierung inklusive Extraktion des
|
||||
Geräte-Zertifikats zuständig ist. Zum Schluss noch der Websocket-Filter, der die Websocket-Verbindungen zum WSM verwaltet.
|
||||
|
||||
Was wären die Nachteile des vorgeschlagenen Refactorings? Zum einen natürlich die Entwicklungskosten, bestehend aus den
|
||||
Entwicklungskosten des Connection Holders, den notwendigen Refactorings im WSM sowie den notwendigen ausführlichen Tests, um zu
|
||||
gewährleisten, dass das System funktioniert wie geplant. Zum anderen käme in die Servicelandschaft bei Heimdall ein weiterer
|
||||
Service hinzu, der potenziell gewartet und beim Onboarding neuer Entwickler:innen berücksichtigt werden muss. Allerdings können
|
||||
die Nachteile relativiert werden, und es gibt auch einige Vorteile: zum einen ist das notwendige Refactoring im WSM minimal,
|
||||
denn nur die Logik für das Persistieren und Überprüfen des Verbindungsstatus kommt hinzu. Die Entwicklung des Connection Holder
|
||||
ist auch nicht sonderlich aufwändig, da er relativ wenige Aufgaben hat. Entsprechend hält sich auch der Overhead beim Onboarding
|
||||
in Grenzen. Der große Vorteil allerdings ist, dass der Connection Holder äußerst selten Updates benötigt. Hier ist zu erwarten,
|
||||
dass die Businesslogik sich sehr selten ändert, also werden Updates hauptsächlich aus Security-Gründen nötig werden. Der große
|
||||
Vorteil ist jetzt, dass WSM-Updates ohne Verbindungsneustarts möglich werden. Insbesondere führt das dazu, dass die Updates des
|
||||
WSM deutlich schneller stattfinden können und außen liegende Systeme weniger beeinflussen. Das führt zu einer verbesserten
|
||||
Time-To-Market bei neuen Features und zu verringerten Abhängigkeiten und Kommunikations-Overheads zu anderen Teams.
|
||||
|
||||
Zusammenfassend können wir schon im aktuellen System zuverlässig dafür sorgen, dass Konfiguration schnell und unkompliziert ohne
|
||||
Neuverbindungen geändert werden kann. Neuverbindungen komplett zu vermeiden dürfte nicht möglich sein, aber wir haben Ideen, wie
|
||||
wir uns in diese Richtung verbessern können. Ich hoffe, ich konnte euch einen guten Einblick in die Herausforderungen geben, vor
|
||||
die uns die langlaufenden Verbindungen in Zusammenhang mit Systemupdates stellen.
|
||||
|
||||
Hier seht ihr noch einmal, wie ihr mich erreichen könnt. Danke fürs Zuhören!
|
||||
Reference in New Issue
Block a user