No Less than Serverless Programmieren für Serverless-Architekturen

Von Filipe Martins & Anna Kobylinska 8 min Lesedauer

Wo Agilität, Skalierbarkeit und Resilienz auf Kostenkontrollen treffen, setzt sich Serverless als bevorzugter Ansatz durch. Das verstärkte Aufkommen innovativer APIs für serverlose Anwendungen ruft neuartige Architekturen auf den Plan.

Im „serverlosen“ Betrieb erfolgt die Inanspruchnahme von Diensten strikt über API-Aufrufe und skaliert bedarfsgetrieben.(©  ArtemisDiana - stock.adobe.com)
Im „serverlosen“ Betrieb erfolgt die Inanspruchnahme von Diensten strikt über API-Aufrufe und skaliert bedarfsgetrieben.
(© ArtemisDiana - stock.adobe.com)

Die granulare Modularität von Serverless-Anwendungen ermöglicht ein einzigartiges Leistungsprofil: Cloud-native Elastizität ohne den üblichen Kostenüberhang, der mit einer IaaS-Bereitstellung zwangsweise einhergeht. Im „serverlosen“ Betrieb gibt es keine Infrastrukturen zu verwalten; der Verbrauch von Diensten erfolgt strikt über API-Aufrufe und skaliert bedarfsgetrieben.

Der Eckpfeiler des Serverless-Computing ist der sogenannte Funktionscode. Die Ausführung dieser Funktionen erfolgt im Rahmen von FaaS-Plattformen (kurz für Functions as a Service) wie AWS Lambda, Azure Functions oder Google Cloud Functions.

Funktionscode: niemals „unter die Haube“ schauen

FaaS-Funktionscode erlaubt die Umsetzung von serverlosen Microservices und ereignisgetriebenen Anwendungsarchitekturen mit Cloud-nativer Skalierbarkeit. Das Beste daran: Die Anwendung ist da, wenn man sie braucht, und kostet nichts, wenn einmal ausnahmsweise „nichts los ist“. Eine AWS Lambda-Funktion in Python könnte zum Beispiel so aussehen:

import json
def lambda_handler(event, context):
   name = event['queryStringParameters']['name']
   # Antwort erstellen
   response = {
      'statusCode': 200,
      'headers': {
         'Content-Type': 'application/json'
      },
      'body': json.dumps({
         'message': f'{name}, DevInsider grüßt Sie!'
      })
   }
   # Rückgabe der Antwort an API Gateway
   return response

Daten der eingehenden Anfrage sind hier im event-Parameter der serverlosen Beispielfunktion enthalten. Relevante Laufzeitinformationen zur Ausführungsumgebung der Lambda-Funktion liefert der Parameter context.

Referenzimplementierung für eine mehrschichtige Serverless-Anwendung in der AWS-Cloud.(Bild:  AWS)
Referenzimplementierung für eine mehrschichtige Serverless-Anwendung in der AWS-Cloud.
(Bild: AWS)

Das Response-Objekt enthält den HTTP-Statuscode, Header und einen Nachrichtenkörper in einem JSON-String. Die serverlose Funktion gibt das Response-Objekt an das API Gateway zurück; dieser Dienst sendet dann die HTTP-Antwort an den Client, fertig. Es gibt keine Infrastruktur zu verwalten und keine Server, die mal (wieder) abstürzen oder gerade neu hochfahren.

Eine vergleichbare Implementierung mit Azure Functions in Python würde etwa wie folgt aussehen:

import azure.functions as func
import json
def main(req: func.HttpRequest) -> func.HttpResponse:
   try:
      # Anfrageparameter extrahieren
      name = req.params.get('name')
      if not name:
         return func.HttpResponse(
            "Bitte geben Sie einen Namen im Query-Parameter an.",
            status_code=400
         )
         # Antwort erstellen
         message = f"{name}, DevInsider grüßt Sie!"
      response_body = json.dumps({"message": message})
      return func.HttpResponse(response_body, mimetype="application/json", status_code=200)
   except Exception as e:
      return func.HttpResponse(
         "Es ist ein Fehler aufgetreten: " + str(e),
         status_code=500
      )

Diese Azure-Function legt als Reaktion auf einen HTTP-Request los und versucht, den Parameter „name“ daraus zu extrahieren. Im Erfolgsfalle generiert sie eine JSON-Antwort, die eine Begrüßungsnachricht enthält, ansonsten gibt sie in der http-Antwort einen Fehler aus.

Funktionscode erlaubt es, die Anwendungslogik in isolierte Aktionen zu disaggregieren und die Ausführung dem Cloud-Anbieter zu überlassen (Stichwort: FaaS). Die resultierenden Anwendungen sind hochgradig modular. Jede Funktion implementiert einen eigenständigen Teil der Anwendungslogik und skaliert unabhängig von dem Rest. Es gibt nichts zu orchestrieren.

Serverlose Microservices und ereignisgetriebene Architekturen

Das Aufkommen von Serverless als eine Alternative zu Containern verändert die Art und Weise, die Microservices-Architekturen entwickelt werden: Jeder Microservice lässt sich als eine separate Funktion implementieren. Dies verbessert Isolation und kann die Komplexität der Bereitstellung großer Anwendungen erheblich reduzieren, wenn man es richtig anstellt.

Serverless Computing bietet sich auch für ereignisgesteuerte Architekturen (kurz: EDA für Event-Driven Architectures) an. Den Ablauf einer solchen Anwendung bestimmen auftretende Ereignisse oder Zustandsänderungen. In einer serverlosen EDA auf der Basis von FaaS werden Funktionen durch Ereignisse wie HTTP- oder Datenbankanfragen ausgelöst – also indirekt auch durch Ereignisse in der realen Welt (wie zum Beispiel IoT-Metriken aus einem QR-Scanner).

Eine FaaS-Funktion in einem Webshop könnte dem Käufer beim Versand der Ware die Sendungsverfolgungsnummer mitteilen. Um die Benachrichtigung per SMS zu versenden, ließe sich AWS Lambda zusammen mit Amazon Simple Notification Service (SNS) wie folgt in Python nutzen:

import boto3
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def send_notification(event, context):
   try:
      bestellungs_id = event['bestellungs_id']
      tracking_nummer = event['tracking_nummer']
      benutzer_telefonnummer = event['benutzer_telefonnummer']
      nachricht = f"Ihre Bestellung {bestellungs_id} wurde versandt! Ihre DevInsider-Sendungsverfolgungsnummer lautet: {tracking_nummer}"
      if not all([bestellungs_id, tracking_nummer, benutzer_telefonnummer]):
         raise ValueError("Erforderliche Informationen fehlen")
      sns_client = boto3.client('sns')
      response = sns_client.publish(
         PhoneNumber=benutzer_telefonnummer,
         Message=nachricht,
         MessageAttributes={
            'AWS.SNS.SMS.SenderID': {
               'DataType': 'String',
               'StringValue': 'DevInsider'
            },
            'AWS.SNS.SMS.SMSType': {
               'DataType': 'String',
               'StringValue': 'Transactional'
            }
         }
      )
      logger.info("SMS erfolgreich gesendet")
      return {'status': 'SMS Benachrichtigung gesendet', 'response': response}
   except Exception as e:
      logger.error(f"Fehler beim Senden der SMS: {str(e)}")
      return {'status': 'Fehler', 'error': str(e)}

Serverlose EDA-Anwendungsarchitekturen zeichnen sich durch ein reaktives Interaktionsmodell aus, während serverlose Microservices eher koordinierte, API-getriebene Interaktionen begünstigen. Die Ausführung von FaaS-Code in Microservice-basierten Anwendungsarchitekturen wird durch API-Aufrufe oder durch andere Microservices angestoßen.

Zustandslosigkeit handhaben

Serverless-Dienste wie AWS Lambda oder Azure Functions führen grundsätzlich zustandslose Funktionen aus. Jede Funktion skaliert unabhängig von anderen und ohne Rücksicht auf deren Zustand. Serverless-Anwendungen müssen ihre Zustandsinformationen extern speichern – ob in Datenbanken, Caches oder anderen Speicherdiensten.

Mit Amplify DataStore bietet eine Datenhaltungslösung mit Offline-Funktionalität und Cloud-Synchronisation. Bei der Implementierung der Mechanismen zum sicheren Abrufen und Speichern von Zustandsinformationen müssen die Entwickler und Entwicklerinnen besondere Sorgfalt walten lassen. Ohne eine durchdachte Planung der Datenarchitektur drohen Leistungseinbuße und Datenverlust.

Jetzt Newsletter abonnieren

Täglich die wichtigsten Infos zu RZ- und Server-Technik

Mit Klick auf „Newsletter abonnieren“ erkläre ich mich mit der Verarbeitung und Nutzung meiner Daten gemäß Einwilligungserklärung (bitte aufklappen für Details) einverstanden und akzeptiere die Nutzungsbedingungen. Weitere Informationen finde ich in unserer Datenschutzerklärung. Die Einwilligungserklärung bezieht sich u. a. auf die Zusendung von redaktionellen Newslettern per E-Mail und auf den Datenabgleich zu Marketingzwecken mit ausgewählten Werbepartnern (z. B. LinkedIn, Google, Meta).

Aufklappen für Details zu Ihrer Einwilligung

Serverless-Backends

In der Entwicklung von Web- und mobilen Anwendungen haben sich serverlose BaaS-Dienste (kurz für Backend as a Service) bewährt.

Beispiel eines Architekturmusters für ein serverloses Backend auf AWS.(Bild:  Baqend)
Beispiel eines Architekturmusters für ein serverloses Backend auf AWS.
(Bild: Baqend)

BaaS verspricht eine skalierbare Bereitstellung von Backend-Diensten wie Datenbankmanagement, Benutzerauthentifizierung oder Push-Benachrichtigungen mit einer einfach zu bedienenden API oder einem SDK, unabhängig davon, wie die zugrundeliegende Infrastruktur implementiert ist. Dadurch können Softwareentwickler ihre Aufmerksamkeit verstärkt auf das Frontend richten.

Zu den bekanntesten Beispielen für serverloses BaaS zählen die Dienste Google Firebase und AWS Amplify sowie quelloffene Frameworks wie Parse. GraphQL, eine Abfragesprache für APIs, harmoniert gut mit serverlosen Architekturen. Es ermöglicht Clients, genau die Daten anzufordern, die sie benötigen, und serverlose Funktionen können diese Abfragen verarbeiten, was die Architektur effizient und skalierbar macht.

Nicht jede Plattform, die sich „Serverless“ nennt, verdient im Übrigen diese Bezeichnung. Den inoffiziellen „Lackmustest“ für Serverless bringen die Developer von Momento, dem Anbieter einer serverlosen Plattform für Caching, Messaging und Vektorsuche, wie folgt auf den Punkt:

  • (es gibt) nichts zu provisionieren und nichts zu verwalten
  • das Kostenprofil ist strikt nutzungsabhängig und hat kein Verbrauchsminimum
  • der Dienst ist ab dem ersten API-Aufruf einsatzbereit
  • eine geplante Downtime darf es nicht geben
  • die Bereitstellung kommt ohne Serverinstanzen aus.

Jamstack und Headless-CMS in serverloser Ausführung

Moderne Web-Entwicklung macht aus serverlosen Technologien ausgiebig Gebrauch. Eine Anwendungsarchitektur namens Jamstack nutzt serverlose Funktionen, um die dynamischen Aspekte einer Website wie Formulareingaben oder Datenbankinteraktionen zu handhaben. Jamstack verwendet eine Kombination aus JavaScript, APIs und (vorab gerendertem) Markup.

In einer Anwendungsarchitektur namens Headless-CMS ist die Präsentationsebene des Content-Management-Systems (CMS) von der Bereitstellung getrennt. Das Frontend besteht aus einer statischen Website. Das Backend ist serverlos implementiert und stellt die benötigten Inhalte über APIs wie RESTful oder GraphQL bereit. Diese Architektur gewährleistet eine hohe Skalierbarkeit und minimiert den Verwaltungsaufwand der Bereitstellung.

AWS Amplify

AWS Amplify ist Amazons Full-Stack-Lösung für die Entwicklung von Full-Stack-Web- und Mobile-Apps auf Basis serverloser Architekturen, darunter serverseitig gerenderter Anwendungen (kurz: SRR für „serverside rendered applications“). Die Umgebung trumpft mit ausgefuchsten Backend-Diensten, einer vollständig verwalteten CI/CD-Pipeline und Cloud-nativer verwalteter Bereitstellung. Azure bietet keine exakte Entsprechung zu AWS Amplify.

Eines der Hauptmerkmale von AWS Amplify ist das Serverless-Backend für das App-UI mit Zugriff auf über 200 AWS-Dienste, darunter DynamoDB, API Gateway und Aurora Serverless. Es unterstützt sichere Authentifizierungsabläufe mit E-Mail-/Social Sign-up und Multi-Faktor-Authentifizierung. Für datengetriebene Anwendungen auf Azure kommt in ähnlichen Szenarien Azure Cosmos DB als global verteilter, multi-modaler Datenbankdienst in Frage.

Amplify integiert sich mit Amazon Pinpoint und AWS CloudWatch für die Überwachung und Analyse des Nutzerverhaltens und der Anwendungsleistung. Amplify Console übernimmt das CI/CD-freundliche Hosting von statischen Webanwendungen und serverlosen Backend-Services.

Sorglos serverlos?

Befürworter serverloser Anwendungsbereitstellung preisen das Potenzial für beschleunigte Markteinführung neuer Features und Cloud-native Skalierbarkeit. Entwicklerinnen und Entwickler, befreit von der Aufgabe der Infrastrukturorchestrierung, können demnach im Serverless-Modell sorglos einfach mal darauf fokussieren, innovative Anwendungen zu coden – oder?

Denkste, ganz ohne Komplikationen ist auch Serverless nicht. Serverless-Plattformen beschränken die maximale Ausführungszeit von Funktionen, die verfügbare Speichermenge und andere Ressourcen. Das verträgt sich nicht gut mit langlaufenden oder besonders ressourcenintensiven Prozessen.

Ein Aufruf von Serverless-Funktionen, die eine längere Zeit nicht in Benutzung sind, geht mit einem Kaltstart der Infrastrukturen und einer verzögerten Ausführung einher. Diese Latenz kann bei zeitkritischen Anwendungen ein großes Problem darstellen. Da eine Serverless-Anwendung typischerweise auf eine Vielzahl von getrennten Diensten zurückgreifen und über APIs kommunizieren muss, kommt ja noch die Netzwerklatenz als besondere Herausforderung hinzu.

Obwohl serverlose Dienste anfängliche Kostenvorteile bringen, können die Ausgaben bei einem höheren Nutzungsumfang einen kleinen Preisschock auslösen. Um effektives Monitoring und Debugging von Serverless kommt man nicht herum. Hierzu sind allerdings spezielle Werkzeuge erforderlich (mehr dazu weiter unten).

Zudem ist es ratsam, die Eignung von Serverless für den jeweils vorliegenden Anwendungsfall im Hinblick auf die Eigenschaften der Zustandslosigkeit ("stateless") und der Ereignissteuerung ("event-driven") zu überprüfen. Jede Serverless-Plattform hat eine eigene API und anbieterspezifische Besonderheiten. Es fehlt ein gemeinsamer Nenner. Dies erschwert sowohl den Anbieterwechsel als auch den Multi-Cloud-Betrieb.

Serverless absichern

Trotz all seiner Vorteile wirft das Serverless-Modell einige nicht zu unterschätzende Herausforderungen auf, insbesondere im Bereich der Sicherheit. Traditionelle Ansätze greifen zu kurz. Um die Sicherheit zu stärken, müssen Developer ihre Anwendungsbereitstellung gezielt gegen Missbrauch schützen. Bewährte Maßnahmen beinhalten:

  • Nutzung von API-Gateways mit eingebauten Sicherheitsfeatures wie Rate Limiting, Authentifizierung, API-Schlüssel, verschlüsselte API-Zugriffe und dergleichen anderen (z.B. Amazon API Gateway oder Azure API Management),
  • Umsetzung feingranularer Zugriffskontrollen auf Funktionsebene (auf AWS mit Amazon Cognito, auf Azure mit Azure Active Directory B2C),
  • Sicherheitsaudits von Abhängigkeiten (Lösungen wie Snyk kommen hier wie gerufen),
  • Verarbeitung ausschließlich legitimer Ereignisse
  • Überwachung von Anwendungen mit spezialisierten Tools wie Datadog oder Splunk.
  • Einsatz von spezialisierten Werkzeugen zur Bedrohungsfrüherkennung wie PureSec oder Protego.

Fazit

Der Einsatz von Serverless-Diensten verspricht erhebliche Vorteile, allen voran schnellere Resultate, granulare Skalierbarkeit, geringere Kosten (je nach Nutzungsverhalten) und eine vereinfachte Betriebsführung durch den Wegfall der Notwendigkeit zur Verwaltung von Cloud-Infrastrukturen. Dennoch sind serverlose Anwendungsarchitekturen wohl kaum das ultimative Rundumglücklich-Paket von Sorglosigkeit, wie man meinen könnte.

Die Verwendung von Serverless-Code geht mit einem erheblichen Risiko von Vendor-Lock-In einher. Der Ansatz fordert spezialisierte Monitoring-Werkzeuge und wirft berechtigte Fragen hinsichtlich der Compliance auf. In diesem Zusammenhang ist es wichtig, Serverless-Code stets im Einklang mit der Gesamtstrategie der Anwendungsentwicklung und -Bereitstellung zu planen und zu implementieren.

Die Entscheidung, Serverless-Technologien zu nutzen, sollte wohlüberlegt sein. Eine gründliche Evaluierung der langfristigen Auswirkungen auf die Systemarchitektur, die Wartbarkeit und die betriebliche Flexibilität gehört bei Serverless ins Pflichtenheft.

(ID:50063058)