Nicht zuletzt durch das Memo, welches Jeff Bezos 2002 an seine Mitarbeiter*innen via E-Mail versandt hatte, haben Web APIs über HTTP an Bedeutung gewonnen. Die Verwendung einer Service-orientierten Architektur (SOA) für bereitgestellte Systeme und Dienste ist mittlerweile unabdingbar. Durch die Cloud und die dadurch geschaffenen, technologischen Möglichkeiten ergeben sich auch neue Wege, um Schnittstellen und APIs bereitzustellen. Microsoft bietet für die Bereitstellung von Web APIs im Wesentlichen zwei Optionen an: ASP.NET Core und Azure Functions. In diesem Beitrag möchte ich auf die jeweiligen Eigenschaften beider Lösungen eingehen und einige Key-Features von Azure Functions hervorheben.
Entwicklung
Zur Entwicklung von Web APIs mit ASP.NET Core werden die von .NET Core unterstützen Sprachen unterstützt (u.a. C#).
Azure Functions unterstützen seit der Functions-Runtime-Version 2.x neben den Sprachen C#, JavaScript und F# nun auch Java, PowerShell, Python und Typescript. Somit richten sich Azure Functions an einen erweiterten Kreis von Entwicklern.
Bereitstellung
Die Bereitstellung von klassischen Web APIs (ASP.NET Core) kann u.a. in Azure innerhalb eines App-Service Plans-erfolgen. Aktuell existiert keine Möglichkeit die Web API über einen Consumption-Plan bereitzustellen. Somit können vergleichsweise hohe Kosten entstehen, insbesondere wenn die Web API kaum bis gar nicht verwendet wird (idle).
Im Gegensatz hierzu können Web APIs, welche als Azure Functions entwickelt wurden, u.a. in einem Consumption-Plan bereitgestellt werden. Hierbei wird unter anderem auf Basis der Anzahl der Aufrufe abgerechnet, wobei 1.000.000 Ausführungen pro Subscription im Monat inklusive sind.
Entwicklungsmodelle
Mit ASP.NET Core Web APIs können RESTful-Dienste erstellt werden. Hierbei werden Controller verwendet, um die Aufrufe zu verarbeiten (ähnlich dem MVC-Pattern). Dies bietet eine gute Basis, um eine Microservice-Architektur abzubilden. Außerdem können Middleware-typische Orchestrierungsfunktionen wie Pipelines bereitgestellt werden.
Azure Functions stellen leichtgewichtige (kleinere) Funktionen dar, welche ebenfalls RESTful-Dienste bereitstellen können und eine Event-getriebene Architektur abbilden. Hierbei ist der Entwickler für die entsprechende Orchestrierung des Funktionsaufrufes zuständig. Somit sind die jeweiligen Anwendungsteile nicht so eng miteinander verbunden, wie es bei Microservices mit Web APIs mit ASP.NET Core der Fall ist. Der Vorteil hierbei ist, dass einzelne Funktionsbausteine einfacher ausgetauscht werden können. Diese lose Kopplung bringt mit sich: Zusammenhänge können hierdurch schwieriger erkannt werden, insbesondere bei komplexeren Anwendungen. Die Fehlersuche eröffnet sich hierdurch ebenfalls schwierig.
Um komplexere Aufrufe in Azure Functions zu orchestrieren, bietet Microsoft mit der Durable-Functions-Erweiterung die Möglichkeit, zustandsbehaftete Funktionen zu schreiben, um z.B. asynchrone HTTP-API-Aufrufe zu orchestrieren.
Initiale Antwortzeiten der API-Aufrufe
Durch die Bereitstellung in Azure innerhalb eines App-Service-Plans werden initiale Funktionsaufrufe auf eine .NET Core Web API in adäquater Zeit beantwortet. Initiale Aufrufe auf eine Azure Functions API (im Consumption-Plan) können dahingegen unter Umständen deutlich länger dauern, da der Function Host bei Nichtverwendung in eine Art Ruhemodus wechselt, um Ressourcen zu sparen. Das bedeutet, der Initiale Aufruf „weckt“ die Funktion auf. Dieser sogenannte Cold-Start kann bis zu 15-20 Sekunden dauern. Wenn dann in geringem Zeitabstand weitere Aufrufe auf die Function stattfinden, antworten diese wieder in adäquater Zeit.
Zusammenfassung und Fazit
Die Entwicklung von Web APIs mit Azure Functions bietet eine einfache Möglichkeit, rasch APIs bereitzustellen. Die leichtgewichtige Bereitstellung in einer serverlosen Umgebung in Azure bietet einen einfachen Einstieg. Entwickler haben eine breitere Auswahl, in welcher Sprache sie ihre API entwickeln möchten. Bei seltenen Aufrufen sind die Azure Functions weniger kostenintensiv und skalieren je Function Host individuell. Bei einer Web API mit ASP geschieht die Skalierung über alle APIs hinweg gleich. Bei der Entwicklung komplexerer Azure Functions ist der Entwickler für die Orchestrierung und die korrekte Ausführung zuständig. Mit Durable Functions werden sie hierbei unterstützt, zustandsbehaftete Funktionen zu entwickeln.
Die Key-Features von Azure Functions:
- Unterstützung von mehreren Programmiersprachen (auch außerhalb .NET)
- Serverlose Anwendung
- Niedrige Kosten
- Leichtgewichtige Entwicklung
Ausblick
Die Erstellung von Web APIs mit Azure Functions erfordern die Bereitstellung von Standardfunktionalität, um Anfragen an die Schnittstelle, wie auch Antworten derselben zu orchestrieren. Hierfür werde ich in den nächsten Wochen in einer mehrteiligen Serie eine Best-Practice-Empfehlung geben, wie APIs mit Azure Functions effizient entwickelt und bereitgestellt werden können. Mithilfe einer Schritt-für-Schritt-Anleitung wird in den einzelnen Teilen über die Organisation der Projektstruktur, über die Verwendung einer Erweiterung zur einfachen Verarbeitung von Requests und Erstellung von Responses, bis hin zur Bereitstellung in ein API-Management diese Best-Practice beschrieben.