Serviceorientierte Architektur mit AWS Lambda: Eine Schritt-für-Schritt-Anleitung

Veröffentlicht: 2022-03-11

Beim Erstellen von Webanwendungen müssen viele Entscheidungen getroffen werden, die Ihrer Anwendung in Zukunft entweder helfen oder sie behindern können, sobald Sie sich darauf festgelegt haben. Entscheidungen wie Sprache, Framework, Hosting und Datenbank sind entscheidend.

Eine solche Wahl ist, ob Sie eine servicebasierte Anwendung mit serviceorientierter Architektur (SOA) oder eine herkömmliche, monolithische Anwendung erstellen möchten. Dies ist eine gängige Architekturentscheidung, die Start-ups, Scale-Ups und Großunternehmen gleichermaßen betrifft.

Serviceorientierte Architektur wird von einer großen Anzahl bekannter Einhörner und Top-Tech-Unternehmen wie Google, Facebook, Twitter, Instagram und Uber verwendet. Scheinbar funktioniert dieses Architekturmuster für große Unternehmen, aber kann es auch für Sie funktionieren?

Serviceorientierte Architektur mit AWS Lambda: Eine Schritt-für-Schritt-Anleitung

Serviceorientierte Architektur mit AWS Lambda: Eine Schritt-für-Schritt-Anleitung
Twittern

In diesem Artikel stellen wir das Thema serviceorientierte Architektur vor und wie AWS Lambda in Kombination mit Python genutzt werden kann, um einfach skalierbare, kosteneffiziente Services zu erstellen. Um diese Ideen zu demonstrieren, werden wir einen einfachen Dienst zum Hochladen und Ändern der Größe von Bildern mit Python, AWS Lambda, Amazon S3 und einigen anderen relevanten Tools und Diensten erstellen.

Was ist serviceorientierte Architektur?

Die serviceorientierte Architektur (SOA) ist nicht neu und hat Wurzeln, die mehrere Jahrzehnte zurückliegen. In den letzten Jahren hat seine Popularität als Muster zugenommen, da es viele Vorteile für Webanwendungen bietet.

SOA ist im Wesentlichen die Abstraktion einer großen Anwendung in viele kommunizierende kleinere Anwendungen. Dies folgt mehreren Best Practices des Software-Engineerings wie Entkopplung, Trennung von Anliegen und Single-Responsibility-Architektur.

Implementierungen von SOA variieren in Bezug auf die Granularität: von sehr wenigen Diensten, die große Funktionsbereiche abdecken, bis hin zu vielen Dutzend oder Hunderten kleiner Anwendungen in einer sogenannten „Microservice“-Architektur. Unabhängig vom Grad der Granularität besteht unter SOA-Praktizierenden allgemein Einigkeit darüber, dass es sich keineswegs um ein kostenloses Mittagessen handelt. Wie viele gute Praktiken im Software-Engineering ist es eine Investition, die zusätzliche Planung, Entwicklung und Tests erfordert.

Was ist AWS Lambda?

AWS Lambda ist ein Service, der von der Amazon Web Services-Plattform angeboten wird. Mit AWS Lambda können Sie Code hochladen, der auf einem von Amazon verwalteten On-Demand-Container ausgeführt wird. AWS Lambda verwaltet die Bereitstellung und Verwaltung von Servern zum Ausführen des Codes, sodass der Benutzer lediglich einen paketierten Codesatz zum Ausführen und einige Konfigurationsoptionen benötigt, um den Kontext zu definieren, in dem der Server ausgeführt wird. Diese verwalteten Anwendungen werden als Lambda-Funktionen bezeichnet.

AWS Lambda hat zwei Hauptbetriebsmodi:

Asynchron/Ereignisgesteuert:

Lambda-Funktionen können als Reaktion auf ein Ereignis im asynchronen Modus ausgeführt werden. Jede Quelle von Ereignissen wie S3, SNS usw. wird nicht blockiert, und Lambda-Funktionen können dies auf vielfältige Weise nutzen, z. B. zum Einrichten einer Verarbeitungspipeline für einige Ereignisketten. Es gibt viele Informationsquellen, und abhängig von der Quelle werden Ereignisse von der Ereignisquelle an eine Lambda-Funktion gepusht oder von AWS Lambda nach Ereignissen abgefragt.

Synchron/Anfrage->Antwort:

Für Anwendungen, die eine synchrone Rückgabe einer Antwort erfordern, kann Lambda im synchronen Modus ausgeführt werden. Typischerweise wird dies in Verbindung mit einem Service namens API Gateway verwendet, um HTTP-Antworten von AWS Lambda an einen Endbenutzer zurückzugeben, Lambda-Funktionen können jedoch auch synchron über einen direkten Aufruf an AWS Lambda aufgerufen werden.

AWS Lambda-Funktionen werden als ZIP-Datei hochgeladen, die Handler-Code zusätzlich zu allen Abhängigkeiten enthält, die für den Betrieb des Handlers erforderlich sind. Nach dem Hochladen führt AWS Lambda diesen Code bei Bedarf aus und skaliert die Anzahl der Server bei Bedarf von null auf Tausende, ohne dass der Verbraucher zusätzliche Eingriffe vornehmen muss.

Lambda-Funktionen als Weiterentwicklung von SOA

Basic SOA ist eine Möglichkeit, Ihre Codebasis in kleine Anwendungen zu strukturieren, um eine Anwendung auf die zuvor in diesem Artikel beschriebenen Weisen zu unterstützen. Daraus resultierend rückt die Art der Kommunikation zwischen diesen Anwendungen in den Fokus. Die ereignisgesteuerte SOA (auch bekannt als SOA 2.0) ermöglicht nicht nur die herkömmliche direkte Service-zu-Service-Kommunikation von SOA 1.0, sondern auch die Weitergabe von Ereignissen in der gesamten Architektur, um Änderungen zu kommunizieren.

Ereignisgesteuerte Architektur ist ein Muster, das auf natürliche Weise eine lose Kopplung und Zusammensetzbarkeit fördert. Durch Erstellen von und Reagieren auf Ereignisse können Dienste ad hoc hinzugefügt werden, um einem vorhandenen Ereignis neue Funktionen hinzuzufügen, und mehrere Ereignisse können zusammengestellt werden, um eine umfassendere Funktionalität bereitzustellen.

AWS Lambda kann als Plattform zum einfachen Erstellen von SOA 2.0-Anwendungen verwendet werden. Es gibt viele Möglichkeiten, eine Lambda-Funktion auszulösen; vom traditionellen Nachrichtenwarteschlangen-Ansatz mit Amazon SNS bis hin zu Ereignissen, die durch das Hochladen einer Datei auf Amazon S3 oder das Senden einer E-Mail mit Amazon SES erstellt werden.

Implementieren eines einfachen Bild-Upload-Dienstes

Wir werden eine einfache Anwendung zum Hochladen und Abrufen von Bildern mithilfe des AWS-Stacks erstellen. Dieses Beispielprojekt enthält zwei Lambda-Funktionen: eine, die im Request->Response-Modus ausgeführt wird und für unser einfaches Web-Frontend verwendet wird, und eine andere, die hochgeladene Bilder erkennt und deren Größe ändert.

Die erste Lambda-Funktion wird asynchron als Reaktion auf ein Datei-Upload-Ereignis ausgeführt, das auf dem S3-Bucket ausgelöst wird, der die hochgeladenen Bilder enthält. Es nimmt das bereitgestellte Bild und ändert die Größe, damit es in ein 400x400-Bild passt.

Die andere Lambda-Funktion stellt die HTML-Seite bereit und bietet sowohl die Funktionalität für einen Benutzer, die Bilder anzuzeigen, deren Größe durch unsere andere Lambda-Funktion geändert wurde, als auch eine Schnittstelle zum Hochladen eines Bildes.

Anfängliche AWS-Konfiguration

Bevor wir beginnen können, müssen wir einige notwendige AWS-Services wie IAM und S3 konfigurieren. Diese werden über die webbasierte AWS-Konsole konfiguriert. Der größte Teil der Konfiguration kann jedoch auch mit dem AWS-Befehlszeilendienstprogramm erreicht werden, das wir später verwenden werden.

Erstellen von S3-Buckets

S3 (oder Simple Storage Service) ist ein Amazon-Objektspeicherdienst, der eine zuverlässige und kostengünstige Speicherung beliebiger Daten bietet. Wir werden S3 verwenden, um die Bilder zu speichern, die hochgeladen werden, sowie die verkleinerten Versionen der Bilder, die wir verarbeitet haben.

Den S3-Service finden Sie im Dropdown-Menü „Services“ in der AWS-Konsole im Unterabschnitt „Storage & Content Delivery“. Beim Erstellen eines Buckets werden Sie aufgefordert, sowohl den Bucket-Namen einzugeben als auch eine Region auszuwählen. Wenn Sie eine Region in der Nähe Ihrer Benutzer auswählen, kann S3 Latenz und Kosten sowie einige regulatorische Faktoren optimieren. Für dieses Beispiel wählen wir die Region „US Standard“. Dieselbe Region wird später zum Hosten der AWS Lambda-Funktionen verwendet.

Es ist erwähnenswert, dass S3-Bucket-Namen eindeutig sein müssen. Wenn der gewählte Name also vergeben ist, müssen Sie einen neuen, eindeutigen Namen wählen.

Für dieses Beispielprojekt erstellen wir zwei Speicher-Buckets mit den Namen „test-upload“ und „test-resized“. Der „Test-Upload“-Bucket wird zum Hochladen von Bildern und zum Speichern des hochgeladenen Bilds verwendet, bevor es verarbeitet und in der Größe geändert wird. Nach der Größenänderung wird das Bild im Bucket „test-resized“ gespeichert und das hochgeladene Rohbild entfernt.

S3-Upload-Berechtigungen

Standardmäßig sind S3-Berechtigungen restriktiv und erlauben externen Benutzern oder sogar nicht administrativen Benutzern nicht, Berechtigungen oder Objekte im Bucket zu lesen, zu schreiben, zu aktualisieren oder zu löschen. Um dies zu ändern, müssen wir als Benutzer mit den Rechten zum Verwalten von AWS-Bucket-Berechtigungen angemeldet sein.

Angenommen, wir befinden uns in der AWS-Konsole, können wir die Berechtigungen für unseren Upload-Bucket anzeigen, indem wir den Bucket nach Namen auswählen, auf die Schaltfläche „Eigenschaften“ oben rechts auf dem Bildschirm klicken und den reduzierten Abschnitt „Berechtigungen“ öffnen.

Um anonymen Benutzern das Hochladen in diesen Bucket zu ermöglichen, müssen wir die Bucket-Richtlinie bearbeiten, um die spezifische Berechtigung zuzulassen, die das Hochladen erlaubt. Dies wird durch eine JSON-basierte Konfigurationsrichtlinie erreicht. Diese Art von JSON-Richtlinien werden in Verbindung mit dem IAM-Service überall in AWS verwendet. Wenn Sie auf die Schaltfläche „Bucket-Richtlinie bearbeiten“ klicken, fügen Sie einfach den folgenden Text ein und klicken Sie auf „Speichern“, um das Hochladen öffentlicher Bilder zuzulassen:

 { "Version": "2008-10-17", "Id": "Policy1346097257207", "Statement": [ { "Sid": "Allow anonymous upload to /", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::test-upload/*" } ] }

Danach können wir überprüfen, ob die Bucket-Richtlinie korrekt ist, indem wir versuchen, ein Bild in den Bucket hochzuladen. Der folgende cURL-Befehl wird den Zweck erfüllen:

 curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'

Wenn eine Antwort im Bereich von 200 zurückgegeben wird, wissen wir, dass die Konfiguration für den Upload-Bucket erfolgreich angewendet wurde. Unsere S3-Buckets sollten jetzt (meistens) konfiguriert sein. Wir werden später auf diesen Dienst in der Konsole zurückkommen, um unsere Bild-Upload-Ereignisse mit dem Aufruf unserer Größenänderungsfunktion zu verbinden.

IAM-Berechtigungen für Lambda

Lambda-Rollen werden alle in einem Berechtigungskontext ausgeführt, in diesem Fall einer vom IAM-Dienst definierten „Rolle“. Diese Rolle definiert alle Berechtigungen, die die Lambda-Funktion während ihres Aufrufs hat. Für die Zwecke dieses Beispielprojekts erstellen wir eine generische Rolle, die zwischen den beiden Lambda-Funktionen verwendet wird. In einem Produktionsszenario wird jedoch eine feinere Granularität der Berechtigungsdefinitionen empfohlen, um sicherzustellen, dass alle Sicherheitsausnutzungen nur auf den definierten Berechtigungskontext beschränkt sind.

Den IAM-Dienst finden Sie im Unterabschnitt „Sicherheit & Identität“ des Dropdown-Menüs „Dienste“. Der IAM-Service ist ein sehr leistungsfähiges Tool zum Verwalten des Zugriffs auf AWS-Services, und die bereitgestellte Benutzeroberfläche kann zunächst etwas überwältigend sein, wenn Sie mit ähnlichen Tools nicht vertraut sind.

Auf der IAM-Dashboard-Seite befindet sich der Unterabschnitt „Rollen“ auf der linken Seite der Seite. Von hier aus können wir die Schaltfläche „Neue Rolle erstellen“ verwenden, um einen mehrstufigen Assistenten aufzurufen, um die Berechtigungen der Rolle zu definieren. Verwenden wir „lambda_role“ als Namen für unsere generische Berechtigung. Nachdem Sie von der Seite zur Namensdefinition fortgefahren sind, wird Ihnen die Option zur Auswahl eines Rollentyps angezeigt. Da wir nur S3-Zugriff benötigen, klicken Sie auf „AWS Service Roles“ und wählen Sie im Auswahlfeld „AWS Lambda“ aus. Ihnen wird eine Seite mit Richtlinien angezeigt, die dieser Rolle zugeordnet werden können. Wählen Sie die Richtlinie „AmazonS3FullAccess“ aus und fahren Sie mit dem nächsten Schritt fort, um die zu erstellende Rolle zu bestätigen.

Es ist wichtig, den Namen und den ARN (Amazon Resource Name) der erstellten Rolle zu notieren. Dies wird beim Erstellen einer neuen Lambda-Funktion verwendet, um die Rolle zu identifizieren, die für den Funktionsaufruf verwendet werden soll.

Hinweis: AWS Lambda protokolliert automatisch alle Ausgaben von Funktionsaufrufen in AWS Cloudwatch, einem Protokollierungsdienst. Wenn diese Funktionalität gewünscht wird, was für eine Produktionsumgebung empfohlen wird, muss den Richtlinien für diese Rolle die Berechtigung zum Schreiben in einen Cloudwatch-Protokollstream hinzugefügt werden.

Der Code!

Überblick

Jetzt können wir mit dem Codieren beginnen. Wir gehen an dieser Stelle davon aus, dass Sie den Befehl „awscli“ eingerichtet haben. Falls nicht, können Sie den Anweisungen unter https://aws.amazon.com/cli/ folgen, um awscli auf Ihrem Computer einzurichten.

Hinweis: Der in diesen Beispielen verwendete Code wurde verkürzt, um die Anzeige auf dem Bildschirm zu vereinfachen. Eine vollständigere Version finden Sie im Repository unter https://github.com/gxx/aws-lambda-python/.

Lassen Sie uns zunächst eine Skelettstruktur für unser Projekt einrichten.

 aws-lambda-python/ - image_list/ - handler.py - list.html - Makefile - requirements.txt - image_resize/ - handler.py - resize.py - Makefile - requirements.txt - .pydistutils.cfg

Wir haben zwei Unterverzeichnisse in unserer Struktur, eines für jede unserer Lambda-Funktionen. In jedem von ihnen haben wir die gemeinsamen Dateien handler.py, Makefile und requirements.txt. Die Datei handler.py enthält die Methode zum Aufrufen der einzelnen Lambda-Funktionen und kann als Einstiegspunkt für die Funktionen betrachtet werden. Die Datei „requirements.txt“ enthält eine Liste unserer Abhängigkeiten, damit wir Anforderungen einfach spezifizieren und aktualisieren können. Schließlich wird der Makefile-Befehl verwendet, um einen einfachen Mechanismus für die Interaktion mit awscli bereitzustellen. Dadurch wird das Erstellen und Aktualisieren unserer Lambda-Funktion viel einfacher.

Sie werden die Datei .pydistutils.cfg im Stammverzeichnis unseres Projektverzeichnisses bemerken. Diese Datei wird benötigt, wenn Sie mit Python unter Homebrew arbeiten. Aufgrund der Methode zur Bereitstellung einer Lambda-Funktion (die im folgenden Abschnitt behandelt wird) wird diese Datei benötigt. Weitere Einzelheiten finden Sie im Repository.

Bildgröße ändern Lambda-Funktion

Code

Beginnend mit der Funktion resize_image frieren wir die Wand-Abhängigkeit, unsere Bildverarbeitungsbibliothek, ein, indem wir Wand==0.4.2 in requirements.txt speichern. Dies ist die einzige Abhängigkeit für unsere Lambda-Funktion image_resize. Die resize_image-Funktion in resize.py muss eine Bildressource aus der Wand-Bibliothek handhaben und ihre Größe gemäß den angegebenen Breiten- und Höhenparametern ändern. Um das Bild, dessen Größe geändert wird, beizubehalten, verwenden wir einen „Best-Fit“-Größenanpassungsalgorithmus, der das Bildverhältnis des Originalbilds beibehält, während die Bildgröße so reduziert wird, dass sie in die angegebene Breite und Höhe passt.

 def resize_image(image, resize_width, resize_height): ... original_ratio = image.width / float(image.height) resize_ratio = resize_width / float(resize_height) # We stick to the original ratio here, regardless of what the resize ratio is if original_ratio > resize_ratio: # If width is larger, we base the resize height as a function of the ratio of the width resize_height = int(round(resize_width / original_ratio)) else: # Otherwise, we base the width as a function of the ratio of the height resize_width = int(round(resize_height * original_ratio)) if ((image.width - resize_width) + (image.height - resize_height)) < 0: filter_name = 'mitchell' else: filter_name = 'lanczos2' image.resize(width=resize_width, height=resize_height, filter=filter_name, blur=1) return image

Nachdem dies aus dem Weg geräumt ist, muss eine Handler-Funktion das von einem in S3 hochgeladenen Bild generierte Ereignis akzeptieren, es an die Funktion resize_image und das resultierende Bild mit geänderter Größe speichern.

 from __future__ import print_function import boto3 from wand.image import Image from resize import resize_image def handle_resize(event, context): # Obtain the bucket name and key for the event bucket_name = event['Records'][0]['s3']['bucket']['name'] key_path = event['Records'][0]['s3']['object']['key'] response = boto3.resource('s3').Object(bucket_name, key_path).get() # Retrieve the S3 Object # Perform the resize operation with Image(blob=response['Body'].read()) as image: resized_data = resize_image(image, 400, 400).make_blob() # And finally, upload to the resize bucket the new image s3_connection.Object('test-resized', key_path).put(ACL='public-read', Body=resized_data) # Finally remove, as the bucket is public and we don't want just anyone dumping the list of our files! s3_object.delete()

Bereitstellen

Wenn der Code vollständig ist, muss er als neue Lambda-Funktion auf Amazon Lambda hochgeladen werden. Hier kommt das Makefile ins Spiel, das der Verzeichnisstruktur hinzugefügt wurde. Dieses Makefile wird verwendet, um die von uns erstellten Lambda-Funktionsdefinitionen bereitzustellen.

 ROLE_ARN = arn:aws:iam::601885388019:role/lambda_role FUNCTION_NAME = ResizeImage REGION = us-west-1 TIMEOUT = 15 MEMORY_SIZE = 512 ZIPFILE_NAME = image_resize.zip HANDLER = handler.handle_resize clean_pyc : find . | grep .pyc$ | xargs rm install_deps : pip install -r requirements.txt -t . build : install_deps clean_pyc zip $(ZIPFILE_NAME) -r * create : build aws lambda create-function --region $(REGION) \ --function-name $(FUNCTION_NAME) \ --zip-file fileb://$(ZIPFILE_NAME) \ --role $(ROLE_ARN) \ --handler $(HANDLER) \ --runtime python2.7 \ --timeout $(TIMEOUT) \ --memory-size $(MEMORY_SIZE) update : build aws lambda update-function-code --region $(REGION) \ --function-name $(FUNCTION_NAME) \ --zip-file fileb://$(ZIPFILE_NAME) \ --publish

Die Hauptfunktionen dieses Makefiles sind „Erstellen“ und „Aktualisieren“. Diese Funktionen packen zuerst das aktuelle Verzeichnis, das den gesamten Code darstellt, der zum Ausführen der Lambda-Funktion erforderlich ist. Als Nächstes werden alle in der Datei requirements.txt angegebenen Abhängigkeiten im aktuellen Unterverzeichnis installiert, um sie zu packen. Der Paketierungsschritt komprimiert den Inhalt des Verzeichnisses, um ihn später mit dem Befehl „awscli“ hochzuladen. Unser Makefile kann für die Verwendung in der anderen Lambda-Funktionsdefinition angepasst werden.

Im Dienstprogramm Makefile definieren wir einige Variablen, die zum Erstellen/Aktualisieren unseres Images erforderlich sind. Konfigurieren Sie diese nach Bedarf, damit die Makefile-Befehle für Sie richtig funktionieren.

  • ROLE_ARN : Dies ist der Amazon-Ressourcenname, der unsere Rolle identifiziert, unter der die Lambda-Funktion ausgeführt wird.
  • FUNCTION_NAME : Der Name der Lambda-Funktion, die wir erstellen/aktualisieren.
  • REGION : Die Region, in der die Lambda-Funktion erstellt/aktualisiert wird.
  • TIMEOUT : Timeout in Sekunden, bevor ein Lambda-Aufruf beendet wird.
  • MEMORY_SIZE : Größe des Arbeitsspeichers in Megabyte, auf den die Lambda-Funktion Zugriff hat, wenn sie aufgerufen wird.
  • ZIPFILE_NAME : Der Name des gezippten Pakets, das den Lambda-Funktionscode und Abhängigkeiten enthält.
  • HANDLER : Der absolute Importpfad der Handler-Funktion in Punktnotation.

Nach der Konfiguration erzeugt das Ausführen des Befehls make create etwas Ähnliches wie die folgende Ausgabe:

 $ make create pip install -r requirements.txt -t . ... find . | grep .pyc| xargs rm zip image_resize.zip -r * ... aws lambda create-function --region ap-northeast-1 \ --function-name ResizeImage2 \ --zip-file fileb://image_resize.zip \ --role arn:aws:iam::11111111111:role/lambda_role \ --handler handler.handle_resize \ --runtime python2.7 \ --timeout 15 \ --memory-size 512 { "CodeSha256": "doB1hsujmZnxZHidnLKP3XG2ifHM3jteLEBvsK1G2nasKSo=", "FunctionName": "ResizeImage", "CodeSize": 155578, "MemorySize": 512, "FunctionArn": "arn:aws:lambda:us-west-1:11111111111:function:ResizeImage", "Version": "$LATEST", "Role": "arn:aws:iam::11111111111:role/lambda_role", "Timeout": 15, "LastModified": "2016-01-10T11:11:11.000+0000", "Handler": "handler.handle_resize", "Runtime": "python2.7", "Description": "" }

Testen

Nach dem Ausführen des Erstellungsbefehls kann die Größenänderungsfunktion für unsere Bilder verwendet werden, sie wurde jedoch nicht mit dem S3-Bucket verbunden, um Ereignisse zu empfangen. Wir können die Funktion dennoch über die AWS-Konsole testen, um sicherzustellen, dass die Funktion S3-Datei-Upload-Ereignisse ordnungsgemäß verarbeitet. Wählen Sie im AWS Lambda-Dashboard, das Sie im Unterabschnitt „Compute“ der Dropdown-Liste „Services“ finden, den Namen der von uns erstellten Funktion aus. Diese Lambda-Funktionsdetailseite bietet ein Dropdown-Menü mit der Bezeichnung „Aktionen“, das eine Option mit der Bezeichnung „Testereignis konfigurieren“ enthält.

Wenn Sie darauf klicken, wird ein Modal geöffnet, in dem Sie ein Testereignis und einige Beispielvorlagen angeben können. Wählen Sie das Beispiel „S3 Put“ und ersetzen Sie alle Erwähnungen eines Bucket-Namens durch den Namen des eingerichteten Buckets. Sobald dies konfiguriert wurde, wird die nachfolgende Verwendung der Schaltfläche „Test“ auf der Seite der Lambda-Funktion die Lambda-Funktion aufrufen, als ob das zuvor konfigurierte Ereignis wirklich aufgetreten wäre.

Um Fehler-Stack-Traces oder Protokollmeldungen zu überwachen, können Sie den Protokollstream in Cloudwatch anzeigen. Eine neue Protokollgruppe wurde gleichzeitig mit der Erstellung der Lambda-Funktion erstellt. Diese Log-Streams sind nützlich und können in andere Dienste geleitet werden.

Verbindung zu S3-Bucket-Ereignissen

Erweitern Sie im S3-Dashboard den reduzierten Abschnitt „Ereignisse“ im Menü „Eigenschaften“, um das Formular „Ereignisbenachrichtigungen“ anzuzeigen. Die Pflichtfelder, die wir ausfüllen müssen, sind die Eingaben „Ereignisse“ und „Senden an“. Wählen Sie unter „Ereignisse“ das Ereignis „Objekt erstellt (alle)“ aus. Dies ermöglicht das Abfangen aller Ereignisse, die ein Objekt im Upload-Bucket erstellen. Wählen Sie für den Eingang „Gesendet an“ das Optionsfeld „Lambda-Funktion“. Es erscheint ein neuer Abschnitt mit einem Dropdown-Menü, das die Lambda-Funktion „ResizeImage“ enthält, die wir als Option konfiguriert haben. Beim Klicken auf „Speichern“ werden nun alle „Objekt erstellt“-Ereignisse als Eingabe an den Aufruf der Lambda-Funktion „ResizeImage“ weitergeleitet.

Wir haben jetzt die Kernfunktionalität der Anwendung. Lassen Sie uns einen weiteren cURL-Test durchführen, um sicherzustellen, dass alles wie erwartet funktioniert. Verwenden Sie cURL, um ein Bild in den S3-Bucket hochzuladen, und überprüfen Sie manuell, ob das Bild in den Resize-Bucket hochgeladen wurde.

 curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'

Beim Ausführen dieses Befehls sollte das in der Größe geänderte Bild nach 50–1000 ms im Bucket „test-resized“ erstellt werden, je nachdem, ob die Lambda-Funktion bereits „aufgewärmt“ war.

Listenbild-Lambda-Funktion

Code

Die Lambda-Funktion ListImage ruft eine Liste von Bildern mit geänderter Größe ab und zeigt sie auf einer HTML-Seite für den Benutzer an. Diese HTML-Seite bietet dem Benutzer auch die Möglichkeit, eigene Bilder hochzuladen. Jinja2 wird in der Funktion zum Rendern von HTML aus einer Vorlagendefinition verwendet. Diese Anforderungen werden wie zuvor in der Datei requirements.txt angegeben.

 from __future__ import print_function import os import boto3 from jinja2 import Environment from jinja2 import FileSystemLoader def _render_template(image_urls): env = Environment(loader=FileSystemLoader(os.path.abspath(os.path.dirname(__file__)))) template = env.get_template('list.html') rendered_template = template.render(image_urls=image_urls) return rendered_template def handle_list_image(event, context): bucket = boto3.resource('s3').Bucket('test-resized') image_summaries = sorted((image_summary for image_summary in bucket.objects.all()), key=lambda o: o.last_modified) image_urls = [] for summary in image_summaries: image_urls.append( boto3.client('s3').generate_presigned_url( 'get_object', Params={ 'Bucket': summary.bucket_name, 'Key': summary.key } ) ) return {'htmlContent': _render_template(image_urls)}
 <html> <head> <title>List Images</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <script> var uploadImage = (function () { var inProgress = false; return function () { if (inProgress) { return; } inProgress = true; var formData = new FormData(); var fileData = $('#image-file').prop('files')[0]; formData.append('key', parseInt(Math.random() * 1000000)); formData.append('acl', 'public-read'); formData.append('file', fileData); $.ajax({ url: 'https://test-upload.s3.amazonaws.com/', type: 'POST', data: formData, processData: false, contentType: false, success: function (data) { window.location.reload(); } }); } })(); </script> <style type="text/css"> .image__container { float: left; width: 30%; margin-left: 2.5%; margin-right: 2.5%; max-width: 400px; } </style> </head> <body> <nav> <input type="file" onchange="uploadImage()" value="Upload Image" /> </nav> <section> {% for image_url in image_urls %} <div class="image__container"> <img src="{{ image_url }}" /> </div> {% endfor %} </section> </body> </html>

Auch hier können wir das vorherige Makefile ändern und den create-Befehl verwenden, um unsere Lambda-Funktion bereitzustellen.

API-Gateway

Die Lambda-Funktion „ImageList“ ist vollständig, kann jedoch keinem Benutzer bereitgestellt werden. Dies liegt daran, dass Lambda-Funktionen nur entweder als Reaktion auf ein Ereignis von einem anderen Dienst oder programmgesteuert aufgerufen werden können. Hier kommt der Amazon AWS API Gateway-Service ins Spiel. API Gateway finden Sie im Unterabschnitt „Anwendungsdienste“.

API Gateway ist eine Möglichkeit, Endpunkte als eine Reihe von Ressourcen und Methoden zu modellieren, im Wesentlichen eine REST-Schnittstelle. Zusätzlich zur Bereitstellung einer Einrichtung zum Validieren und Transformieren von Anfragen führt API Gateway andere Funktionen aus, wie z. B. das Bereitstellen von Drosselungs-/Ratenbegrenzungsanfragen.

Erstellen Sie im API Gateway-Dashboard eine neue API zum Bereitstellen der ListImage-Funktion. Der Name und die Beschreibung können nach Ihren Wünschen festgelegt werden. Klicken Sie nach der Erstellung auf den Namen der neuen API, um auf die API-Details zuzugreifen. Erstellen Sie eine neue Ressource für die Stamm-URL „/“. Diese URL wird verwendet, um die HTML-Seite bereitzustellen.

Fügen Sie beim Anzeigen der Details für die Stammressourcenseite eine GET-Methode hinzu. Stellen Sie den „Integration Type“ auf „Lambda Function“, legen Sie die „Lambda Region“ auf „us-west-1“ oder Ihre ausgewählte Region fest und geben Sie den Namen der ListImage Lambda-Funktion ein.

Bevor wir damit beginnen können, unsere Antwort einer HTML-Ausgabe zuzuordnen, müssen wir ein „Modell“ definieren, das ein Schema für die Antwort vom Server definiert, zusätzlich zur Zuordnung dieser Antwort zu einem Inhaltstyp. Wählen Sie den Abschnitt „Modelle“ für die API und klicken Sie auf „Erstellen“, um ein neues Modell zu erstellen. Geben Sie dem Modell den Namen „HTML“ mit einem Inhaltstyp von „text/html“ und definieren Sie das Schema wie folgt:

 { "$schema": "http://json-schema.org/draft-04/schema#", "title" : "HTML", "type" : "object" }

Wählen Sie im API-Dashboard die von uns erstellte Ressource aus und navigieren Sie zum Abschnitt „Integration Response“. Dieser Abschnitt definiert jede Transformation, die nach Erhalt einer Antwort von der Lambda-Funktion verarbeitet werden soll, bevor die Antwort an den letzten Schritt weitergeleitet wird.

Öffnen Sie den Abschnitt „Zuordnungsvorlagen“ und fügen Sie einen neuen „Inhaltstyp“ von „text/html“ hinzu. Entfernen Sie gleichzeitig den alten „Content Type“. Ändern Sie rechts das Drop-down-Menü von „Output Passthrough“ zu „Mapping template“. Dadurch können wir das von API Gateway akzeptierte Roh-JSON ändern und stattdessen den HTML-Inhalt in der Eigenschaft „htmlContent“ unserer zurückgegebenen Daten verwenden. Geben Sie für die Zuordnungsvorlage „$input.htmlContent“ als Vorlage an. Ändern Sie schließlich den Abschnitt „Method Response“, indem Sie „application/json“ aus „Response Models for 200“ entfernen und stattdessen „text/html“ hinzufügen.

Um zum Dashboard für die API zurückzukehren, gibt es oben links auf der Seite eine Schaltfläche mit der Bezeichnung „API bereitstellen“. Klicken Sie auf diese Schaltfläche, um die API mit den angegebenen Ressourcen, Methoden, Modellen und Zuordnungen zu aktualisieren oder zu erstellen. Sobald dies erledigt ist, wird eine URL für die ausgewählte Bereitstellungsphase angezeigt (standardmäßig Staging). Endlich ist das Beispiel fertig! Sie können einige Dateien hochladen, um die verkleinerten Bilder zu testen und anzuzeigen.

Einpacken

AWS ist ein großer Dienst und wird in absehbarer Zeit nicht verschwinden. Obwohl man immer auf die Herstellerbindung achten muss, bietet AWS Lambda einen relativ dünnen Service mit einer Vielzahl zusätzlicher Konfigurationsoptionen. Die Nutzung der von AWS bereitgestellten Services zur Implementierung leicht skalierbarer und wartbarer Anwendungen bietet den größten Nutzen aus der Nutzung der AWS-Plattform. AWS Lambda bietet eine elegante, skalierbare und kostengünstige Lösung, die von einer Unternehmensplattform unterstützt wird, die von einer sehr großen Anzahl von Verbrauchern verwendet wird. Ich glaube, dass „serverlose“ Anwendungen der Weg der Zukunft sind. Teilen Sie uns Ihre Meinung in den Kommentaren unten mit.