Ich werde oft gefragt: "Jaspal, ich will meine KI Anwendung in Azure betreiben - was muss ich beachten?"
Und ehrlich gesagt: Die Liste ist lang. Einen Punkt möchte ich in diesem Blogpost aber besonders hervorheben, weil er maßgeblichen Einfluss auf eure Anwendungsarchitektur und die Gestaltung eurer Azure Ressourcen hat.
Und zwar das "230 Sekunden Limit" in der Azure Cloud. Was bedeutet das?
Das Szenario
Stellt euch folgendes vor: Ihr habt eine KI Anwendung entwickelt. Der User gibt seine Daten ein und eure Anwendung generiert daraus einen Blogpost samt Bild. Cool - lokal seid ihr überwältigt, wie gut alles funktioniert. Eure Erwartung: In der Cloud läuft das genauso!
Ja - bedingt. Wenn ihr eure Anwendung als Azure App Service (Web App) betreibt, klappt das Szenario nur, solange die Erstellung des Blogposts weniger als knapp 4 Minuten dauert:

Braucht eure App länger als 230 Sekunden, um die Anfrage abzuarbeiten, bekommt ihr einen Timeout Fehler (siehe auch die offizielle App Service FAQ von Microsoft):

Bei Azure Container Apps liegt die Grenze übrigens bei 240 Sekunden - also praktisch dieselbe Größenordnung. Das Problem bleibt dasselbe.
Warum ist das so?
Vor eurer App sitzt ein Load Balancer, der eingehende Anfragen auf eure Instanzen verteilt. Liefert eure App innerhalb von 230 Sekunden keine Antwort, beendet er die Verbindung. Eure App arbeitet im Hintergrund vielleicht sogar weiter, aber der User bekommt das Ergebnis nie zu sehen.
Und das hat auch seinen Grund: Je länger ein Request offen bleibt, desto mehr Aufwand ist es für die Cloud, Verbindungen und States aufrechtzuerhalten. Bei Sessions, die Minuten oder gar Stunden dauern, entstehen schnell ganz andere Probleme.
Wie umgehe ich das Problem?
Ganz einfach: Überlegt euch, wie ihr eure Anwendungsarchitektur gestaltet. Es gibt viele Best Practices und Guidelines, doch unterm Strich gilt immer: Eine langlaufende Aktion sollte im Hintergrund ausgeführt werden - und bei Fertigstellung wird der User benachrichtigt.

Dieses Pattern begegnet euch im Azure Portal übrigens ständig: Ihr beauftragt die Erstellung einer Ressource, das Portal zeigt euch sofort eine Benachrichtigung, dass die Ressource im Hintergrund erstellt wird, und ihr könnt in der Zwischenzeit ganz normal weiterarbeiten:

Sobald die Ressource erstellt wurde, bekommt ihr eine weitere Benachrichtigung:

Die Abarbeitung läuft im Hintergrund und darf auch länger dauern, ohne den User zu blockieren.
So machen wir das in unseren Anwendungen
In unserem Tech Stack (.NET Core) nutzen wir Background Worker, um langwierige Aufgaben abzuarbeiten:

Die API bzw. das Frontend nimmt die Anfrage des Users entgegen und antwortet sofort mit der Info, dass die Aufgabe im Hintergrund verarbeitet wird. Der Background Worker erstellt dann den Blogpost. Sobald er fertig ist, ruft er eine Logic App über einen HTTP Trigger auf. Die Logic App schickt dem User eine Mail mit der Info, dass sein Blogpost fertig ist.
Der Vorteil? Der Background Worker ist nicht vom User Request abhängig. Er läuft so lange, wie die App läuft - und mit aktiviertem "Always On" wird die App auch bei Leerlauf nicht entladen. So lassen sich auch sehr langwierige Aufgaben mit diesem Pattern bewältigen.
Aber Achtung: Bei einem Deployment, einem Neustart oder einer Plattformwartung wird eure App neu gestartet - und Jobs, die nur im Arbeitsspeicher liegen, gehen dabei verloren. Bei mehreren Instanzen (Scale-out) kommt dazu, dass jede Instanz ihren eigenen Background Worker hat. Für kritische Aufgaben empfehlen wir daher, eine Queue dazwischenzuschalten (z.B. Azure Storage Queue oder Service Bus): Die API legt den Auftrag in die Queue, der Background Worker holt ihn sich ab. Geht etwas schief, bleibt der Auftrag erhalten und wird erneut verarbeitet.
Kein Background Worker? Kein Problem!
Falls euer Tech Stack keine Background Worker unterstützt: Ihr könnt die Verarbeitung auch direkt von der API an eine Logic App delegieren und dem User sofort die Info geben, dass alles im Hintergrund läuft.

Fazit
Solche Patterns werdet ihr in Cloud Umgebungen immer wieder finden, oft unter dem Namen "asynchrone Verarbeitung". Die Message ist aber immer dieselbe: Anfragen von Usern an eure Web App sollten schnell eine Antwort bekommen, langwierige Aufgaben gehören in den Hintergrund. Wer das von Anfang an in der Architektur berücksichtigt, erlebt beim Go-Live in Azure keine bösen Überraschungen. ;)
Kommentare
Kommentar hinterlassen
Kommentare werden moderiert und bei Regelverstößen oder Missbrauch ausnahmslos entfernt.