iX 8/2016
S. 78
Review
Serverless Programming
Aufmacherbild

Abkehr vom monolithischen Entwickeln

Tröpfchenweise

In der Cloud bieten sich Entwicklern neue Wege, Anwendungen ressourcensparend und effizient zu hosten. Serverless Programming hat das Potenzial, völlig neue Softwarearchitekturen zu etablieren, bei denen Anbieter von Plattformdiensten das Ausführen des Codes sowie Aspekte wie Skalierbarkeit oder Ausfallsicherheit sicherstellen.

Zum Entwickeln und Betreiben von Applikationen in der Cloud bietet Serverless Programming entscheidende Vorteile im Vergleich zum klassischen monolithischen Ansatz. Es befreit Entwickler von administrativen Aufgaben, wie dem Konfigurieren und Warten von Applikationsservern, dem Bereitstellen ausreichender Ressourcen im Rahmen der Skalierbarkeit oder dem Garantieren der Ausfallsicherheit.

Serverless Programming verzichtet allerdings keineswegs auf einen Applikationsserver. Vielmehr stellen Cloud-Anbieter eine Laufzeitumgebung bereit, die sie hosten und betreiben. Der Entwickler muss somit dazu seinen Code lediglich hochladen. Der Platform-as-a-Service-Anbieter (PaaS) sorgt für das Ausführen des Codes und kümmert sich etwa um Skalierbarkeit und Ausfallsicherheit. Der Entwickler stellt den Programmcode im Normalfall nicht als komplette Anwendung bereit, sondern in Form von Ausführungseinheiten. Die Aufteilung von Funktionen in Services kann als Gegenmodell zu monolithischen Anwendungen verstanden werden. Daher spricht man in diesem Zusammenhang auch von Microservices.

Klein, aber fein

Im Gegensatz zum klassischen Cloud-Computing müssen Entwickler beim Serverless Programming keine eigenen virtuellen Maschinen verwalten. Dies befreit sie vor allem von administrativen Aufgaben. Serverless Programming bietet zudem finanzielle Vorteile, weil Anbieter solcher Plattformen in der Regel verbrauchsabhängig abrechnen; der Kunde zahlt nur für das Ausführen seines Codes; wird der Software-Code nicht ausgeführt, fallen keine Gebühren an. Auf der anderen Seite birgt der Einsatz von Microservices neue Herausforderungen. So verbietet sich das in der Vergangenheit praktizierte monolithische Entwickeln von Anwendungen bei Microservices. Es eignet sich daher eher für von Grund auf neu zu entwickelnde Anwendungen.

Verschiedene Cloud-Anbieter ermöglichen das Bereitstellen von Code als Microservices. Neben AWS Lambda sind besonders Iron.io, Microsoft Azure Functions, Google Cloud Functions und Bluemix OpenWhisk (IBM) erwähnenswert. Allerdings sind Azure Functions und Google Cloud Functions recht neu und haben noch Preview-Status. Am längsten im Geschäft ist iron.io, dem bereits zahlreiche größere Kunden vertrauen. Für AWS Lambda spricht vor allem die gute Integration in das AWS-Ökosystem. Weitere Einzelheiten zu deren übrigen Anbietern finden sich im Kasten „Alternativen zu AWS Lambda“.

Lambda unter der Lupe

AWS Lambda integriert weitere Dienste von Amazon, etwa solche zur Datenspeicherung (S3, DynamoDB), Messaging-Services (SQS), Security-Dienste oder Services zum Generieren von Events. Dadurch lassen sich komplexere Anwendungen auf Basis von Microservices aufbauen. Die enge Verflechtung der AWS-Dienste ermöglicht eine ganze Reihe interessanter Einsatzszenarien.

Häufig anzutreffen ist das Event-basierte Ausführen von Lambda-Funktionen, etwa beim Ablegen einer neuen Datei im Object Store S3. Damit lässt sich beispielsweise das Verarbeiten strukturierter Dateien im JSON- oder XML-Format automatisieren. Um typische Beispiele handelt es sich beim Verarbeiten von Log-Dateien oder das Prozessieren von Produktionsdaten. Quellen für solche Events können weitere Amazon-AWS-Dienste wie DynamoDB, Kinesis, SNS, SES oder Cognito sein. Damit eignet sich der Dienst außerdem für die Verarbeitung großer Datenmengen in Echtzeit, was besonders bei Big-Data-Szenarien erforderlich ist.

Lambda-Funktionen müssen nicht notwendigerweise durch Events ausgelöst werden. Entwickler können sie mit API-Gateways als Webservice publizieren und so für andere Anwendungen (innerhalb und außerhalb der eigenen Amazon-Umgebung) zur Verfügung stellen. Dieser Ansatz bietet sich insbesondere für das Umsetzen größerer Anwendungen als Microservices an.

Überdies lässt sich Lambda im Rahmen der Infrastrukturautomatisierung verwenden. Amazon bietet hierfür den CloudFormation-Dienst. Dieser erlaubt es, ganze Umgebungen (virtuelle Maschinen, Netzwerke, Datenbanksysteme) per Knopfdruck anzulegen. Allerdings ermöglicht CloudFormation keine direkte Ausführung von prozeduralem Code. AWS Lambda lässt sich in diesem Zusammenhang zum Durchführen komplexer Konfigurationen einsetzen, die nicht mehr mit CloudFormation abgebildet werden können, sondern die in einem eigenen Programm gelöst werden müssen.

Sorgfältige Planung beim Lambda-Entwurf

Vor dem Einsetzen einer Lambda-Funktion muss der Entwickler die Region festlegen, in der Amazon sie hostet. Das Unternehmen teilt seine globalen Rechenzentren in Regionen auf, um neben hoher Verfügbarkeit geringe Latenzzeiten für den Kunden zu gewährleisten. Allerdings bietet es neuere Dienste häufig nicht in allen Regionen an. Zum aktuellen Zeitpunkt gibt es AWS Lambda in den Regionen US East (N. Virginia), US West (Oregon), EU (Irland), EU (Frankfurt) und Asia Pacific (Tokyo).

Außerdem muss der Entwickler beim Entwerfen einer Lambda-Funktion bestimmte Aspekte berücksichtigen: Er muss den Ressourcenbedarf der Anwendung abschätzen und konfigurieren. Das ist insbesondere aus Kostensicht relevant. Zudem muss er gewisse Ressourcenlimits beachten. Eine Lambda-Funktion darf eine maximale Laufzeit von 300 Sekunden aufweisen, andernfalls wird ein „exceeded limits“-Fehler zurückgegeben. Zudem ist der temporäre Festplattenspeicher auf 512 MByte pro Funktionsaufruf begrenzt. Die gezippte Funktion darf inklusive ihrer Abhängigkeiten 50 MByte nicht überschreiten. An Sprachen versteht Lambda zum aktuellen Zeitpunkt Node.js, Python sowie Java.

Hinsichtlich des Verbrauchs während des Funktionsablaufs muss der Entwickler lediglich den benötigten Speicher abschätzen. Er kann den allozierten Speicher zwischen 128 MByte und 1536 MByte RAM in Schritten von 64 MByte festlegen. Aus Effizienzgründen sollte er daher den Speicherbedarf seiner Funktion testen und anpassen. Wird ihr zu wenig Speicher zugeteilt, bricht sie mit einer Fehlermeldung ab. Bei höherer Zuteilung entstehen im Gegenzug höhere Kosten.

Konfiguration (und Verwaltung)

AWS Lambda im Zusammenspiel mit S3 und DynamoDB (Abb. 1)

Neben dem eigentlichen Bereitstellen der Lambda-Funktion gilt es, einige Konfigurationsaspekte zu beachten, was sich anhand eines Auftragsverarbeitungssystems für eingehende Kundenaufträge skizzieren lässt (Abbildung 1):

1. Der Kunde setzt über ein Portal einen Auftrag ab. Dieser wird als JSON-Datei in AWS S3 abgelegt.

2. Die Ablage der json-Datei in S3 generiert ein Event, das wiederum eine AWS-Lambda-Funktion auslöst.

3. Die Lambda-Funktion liest das JSON-Dokument aus und speichert die zu verarbeiteten Daten in eine DynamoDB-Datenbank.

Erstellung eines Events in S3 (Abb. 2)

Das Anlegen der neuen Bestellung kann über eine Kundenwebseite erfolgen. Eventuell hat der Kunde direkten Zugriff auf den S3 Bucket. In diesem Beispiel besteht die Bestellung aus einem JSON-Dokument. Andere Formate wie XML sind ebenfalls denkbar. Damit die Ablage einer neuen Bestellung die richtige Lambda-Funktion auslöst, ist für den S3 Bucket ein Event zu konfigurieren (Abbildung 2).

Sobald ein Benutzer eine Bestellung in den S3 Bucket abgelegt hat, wird die AWS-Lambda-Funktion ausgeführt. S3 verwendet dafür das Push Event Model: die auszuführende Lambda-Funktion wird in S3 spezifiziert. Das Listing zeigt eine Implementierung mit Node.js, die die Bestellung im JSON-Format verarbeitet, die relevanten Informationen extrahiert und eine Dynamo-DB-Tabelle updatet.