Wenn meine Applikation mit einer extern gewarteten API kommuniziert, kommt früher oder später der Zeitpunkt, an dem sich dieses API ändert. Abhängig vom Umfang der Änderungen, wie kritisch das API ist und wie die Umstellung selbst erfolgt, gibt es verschiedene Techniken, die für Implementierung und Livegang genutzt werden können.
Diese möchte ich hier kurz zusammenfassen.
Muss API-Migration kompliziert sein?
Im einfachsten Fall läuft die Anbindung des neuen APIs nicht anders als jede andere Entwicklungsaufgabe. Der alte Code wird durch den neuen ersetzt, getestet und deployed. Der Vorteil hierbei liegt auf der Hand: Das Vorgehen ist bekannt und die Umsetzung am einfachsten und damit am preiswertesten. Damit das allerdings möglich ist, sind einige Voraussetzungen nötig:
Die Änderungen müssen klein genug und überschaubar sein, so dass sie in einer Umsetzung durchführbar sind. Dies kann der Fall sein, wenn das API nur an einer Stelle verwendet wird. Oder aber die Änderung selbst ist sehr klein; beispielsweise bleibt das API an sich unverändert, aber die URLs ändern sich. Hier lohnt es sich auch zu prüfen, ob weitreichende Änderungen an einem breit genutzten API in einzelne Schritte getrennt werden können, die dann klein genug sind.
Des weiteren sollte der Livegang in absehbarer Zukunft liegen, damit die Änderungen zeitnah übernommen werden können und nicht veralten. Wenn im Projekt z. B. Feature-Flags bereits üblich sind, können diese natürlich genutzt werden, um dieses Problem zu umgehen.
Im Zweifel abstrahieren
Falls diese Bedingungen nicht erfüllt sind, wird eine Abstraktions-Schicht nötig, die die Änderung des APIs vom restlichen Code trennt und so eine der restlichen Applikation gegenüber opake Anbindung des neuen APIs ermöglicht. Diese kann verschiedene Formen annehmen.
Wenn sich die Endpunkte des neuen APIs nicht zu stark von denen des alten unterscheiden, kann ein Proxy eingeführt werden. Dieser kann dann schrittweise angepasst werden, so dass sich das Interface gegenüber der restlichen Applikation ändert, während nach wie vor das alte API angesprochen wird. Das neue API kann dann ebenfalls angebunden und per Feature-Flag angesprochen werden. Nach erfolgreicher Umstellung kann dieser Proxy wieder entfernt werden. Dieses Vorgehen bietet sich an, wenn die Einführung einer neuen Applikation (des Proxys) in die vorhandene Infrastruktur ohne größere Probleme möglich ist, z. B. bei containerisierten Applikationen.
In einer Microservice-Architektur existiert die Abstraktion des APIs gegenüber der restlichen Applikation möglicherweise bereits in Form eines Services. In diesem Fall kann es sinnvoller sein, einfach den gesamten Service auszutauschen, statt eine weitere Schicht einzuführen.
Falls die Abstraktion per Proxy in einer klassischen, monolithischen Architektur nicht möglich ist, sollte statt dessen nach dem Modell „branch by abstraction“ vorgegangen werden. Für die Klassen und Methoden, die das API verwenden, werden Interfaces definiert, für die es dann zwei Implementierungen gibt: eine für das alte und eine für das neue API. Auch hier ist nach der Umstellung zu prüfen, ob diese Abstraktionen noch sinnvoll sind oder evtl. wieder ausgebaut werden sollten.
Warum Modernisierung scheitert
Ein Leitfaden für Projektverantwortliche
Dieses Whitepaper gibt Dir einen umfassenden Überblick über die wirklichen Herausforderungen der Softwaremodernisierung und zeigt Dir praktische Lösungswege auf. Als besonderes Extra findest Du eine Checkliste, die Dir dabei hilft, die Modernisierung erfolgreich umzusetzen.
Wie geht das ganze Live?
Die Umstellung von breit genutzten und kritischen APIs ist immer mit Unsicherheit verbunden. Ausführliche Tests können hier zu einem gewissen Grad Abhilfe schaffen, in der Regel aber nicht alle Fälle abdecken. Bekanntermaßen findet nichts Fehler besser, als tatsächliche Nutzer. Wenn ein Parallelbetrieb des alten und neuen APIs möglich ist, ist es daher sinnvoll, dies zu nutzen und einen teilweisen Livegang vorzunehmen. Das kann bedeuten, nur einzelne Endpunkte umzustellen (falls das API dies ermöglicht) oder die gesamte Umstellung für nur einen Teil der Endnutzer vor zu nehmen. Im Idealfall werden beide Varianten kombiniert.
Falls es im Projekt noch keine Infrastruktur für A/B-Tests oder canary deployments gibt, kann das ein Anlass sein, diese zu schaffen. Wenn sie einmal eingeführt ist, wird sie genutzt werden.
Oftmals ist der Parallelbetrieb des alten und neuen APIs aber nicht möglich. Dies verhindert nicht nur einen graduellen Livegang, es stellt sich generell die Frage, wie dieser Livegang aussieht. Das hängt davon ab, wie die Applikation mit der Nicht-Erreichbarkeit umgeht und wie lange das API selbst während der Umstellung nicht erreichbar ist.
Wenn die Umstellung kurz und das API nicht zu kritisch ist, kann es sein, dass die in diesem Zeitraum auftretenden Fehler akzeptabel sind und keine weiteren Schritte nötig sind.
Eventuell ist es auch möglich Ausfälle zu vermeiden, indem lesende Requests gegen das API aus einem Cache bedient werden und schreibende Requests in einer Queue zu sammeln und nach der Umstellung abzuarbeiten.
Andernfalls sind Ausfälle in der eigenen Applikation nicht zu vermeiden und es bleibt nur zu klären, ob es möglich und sinnvoll ist, nur einzelne Funktionen abzuschalten oder ob die gesamte Applikation in einen Wartungsmodus gesetzt werden muss.
Übrigens: Tobias hat vor kurzem beschrieben, wie man in 5 Schritten zu einem modernen API kommt; das Thema dürfte euch bestimmt ebenfalls interessieren.
Schreibe einen Kommentar