Architettura orientata ai servizi con AWS Lambda: un tutorial passo-passo
Pubblicato: 2022-03-11Quando si creano applicazioni Web, ci sono molte scelte da fare che possono aiutare o ostacolare la tua applicazione in futuro una volta che ti impegni con esse. Scelte come lingua, framework, hosting e database sono cruciali.
Una di queste scelte è se creare un'applicazione basata sui servizi utilizzando l'architettura orientata ai servizi (SOA) o un'applicazione monolitica tradizionale. Questa è una decisione architettonica comune che colpisce allo stesso modo startup, scale-up e aziende.
L'architettura orientata ai servizi è utilizzata da un gran numero di noti unicorni e aziende top-tech come Google, Facebook, Twitter, Instagram e Uber. Apparentemente, questo modello di architettura funziona per le grandi aziende, ma può funzionare per te?
In questo articolo introdurremo l'argomento dell'architettura orientata ai servizi e come è possibile sfruttare AWS Lambda in combinazione con Python per creare facilmente servizi scalabili ed economici. Per dimostrare queste idee, creeremo un semplice servizio di caricamento e ridimensionamento delle immagini utilizzando Python, AWS Lambda, Amazon S3 e alcuni altri strumenti e servizi pertinenti.
Che cos'è l'architettura orientata ai servizi?
L'architettura orientata ai servizi (SOA) non è nuova, avendo radici da diversi decenni fa. Negli ultimi anni la sua popolarità come modello è cresciuta grazie all'offerta di molti vantaggi per le applicazioni rivolte al Web.
SOA è, in sostanza, l'astrazione di una grande applicazione in molte applicazioni più piccole comunicanti. Ciò segue diverse migliori pratiche dell'ingegneria del software come il disaccoppiamento, la separazione delle preoccupazioni e l'architettura a responsabilità singola.
Le implementazioni di SOA variano in termini di granularità: da pochissimi servizi che coprono vaste aree di funzionalità a molte decine o centinaia di piccole applicazioni in quella che viene definita architettura di "microservizi". Indipendentemente dal livello di granularità, ciò che è generalmente concordato tra i praticanti della SOA è che non si tratta affatto di un pranzo gratuito. Come molte buone pratiche nell'ingegneria del software, si tratta di un investimento che richiederà pianificazione, sviluppo e test aggiuntivi.
Che cos'è AWS Lambda?
AWS Lambda è un servizio offerto dalla piattaforma Amazon Web Services. AWS Lambda ti consente di caricare codice che verrà eseguito su un container on-demand gestito da Amazon. AWS Lambda gestirà il provisioning e la gestione dei server per eseguire il codice, quindi tutto ciò che serve all'utente è un pacchetto di codice da eseguire e alcune opzioni di configurazione per definire il contesto in cui viene eseguito il server. Queste applicazioni gestite sono denominate funzioni Lambda.
AWS Lambda ha due modalità operative principali:
Asincrono/guidato da eventi:
Le funzioni Lambda possono essere eseguite in risposta a un evento in modalità asincrona. Qualsiasi origine di eventi, come S3, SNS e così via, non si bloccherà e le funzioni Lambda possono trarne vantaggio in molti modi, ad esempio stabilendo una pipeline di elaborazione per una catena di eventi. Esistono molte fonti di informazioni e, a seconda dell'origine, gli eventi verranno inviati a una funzione Lambda dall'origine dell'evento o sottoposti a polling degli eventi da AWS Lambda.
Sincrono/Richiesta->Risposta:
Per le applicazioni che richiedono la restituzione di una risposta in modo sincrono, Lambda può essere eseguito in modalità sincrona. In genere viene utilizzato insieme a un servizio chiamato API Gateway per restituire risposte HTTP da AWS Lambda a un utente finale, tuttavia le funzioni Lambda possono anche essere chiamate in modo sincrono tramite una chiamata diretta a AWS Lambda.
Le funzioni di AWS Lambda vengono caricate come file zip contenente il codice del gestore oltre a eventuali dipendenze richieste per il funzionamento del gestore. Una volta caricato, AWS Lambda eseguirà questo codice quando necessario e ridimensionerà il numero di server da zero a migliaia quando richiesto, senza alcun intervento aggiuntivo richiesto dal consumatore.
Lambda funziona come evoluzione della SOA
La SOA di base è un modo per strutturare la tua base di codice in piccole applicazioni per trarre vantaggio da un'applicazione nei modi descritti in precedenza in questo articolo. Da ciò emerge il metodo di comunicazione tra queste applicazioni. La SOA basata sugli eventi (nota anche come SOA 2.0) consente non solo la tradizionale comunicazione diretta da servizio a servizio di SOA 1.0, ma anche la propagazione degli eventi in tutta l'architettura per comunicare il cambiamento.
L'architettura guidata dagli eventi è un modello che promuove naturalmente l'accoppiamento libero e la componibilità. Creando e reagendo agli eventi, è possibile aggiungere servizi ad hoc per aggiungere nuove funzionalità a un evento esistente e diversi eventi possono essere composti per fornire funzionalità più avanzate.
AWS Lambda può essere utilizzato come piattaforma per creare facilmente applicazioni SOA 2.0. Esistono molti modi per attivare una funzione Lambda; dal tradizionale approccio a coda di messaggi con Amazon SNS, agli eventi creati dal caricamento di un file su Amazon S3 o dall'invio di un'e-mail con Amazon SES.
Implementazione di un semplice servizio di caricamento delle immagini
Creeremo una semplice applicazione per caricare e recuperare immagini utilizzando lo stack AWS. Questo progetto di esempio conterrà due funzioni lambda: una in esecuzione in modalità richiesta->risposta che verrà utilizzata per servire il nostro semplice frontend web e un'altra che rileverà le immagini caricate e le ridimensionerà.
La prima funzione lambda verrà eseguita in modo asincrono in risposta a un evento di caricamento file attivato sul bucket S3 che ospiterà le immagini caricate. Prenderà l'immagine fornita e la ridimensionerà per adattarla a un'immagine 400x400.
L'altra funzione lambda servirà la pagina HTML, fornendo sia la funzionalità per consentire a un utente di visualizzare le immagini ridimensionate dall'altra nostra funzione Lambda, sia un'interfaccia per caricare un'immagine.
Configurazione AWS iniziale
Prima di poter iniziare, dovremo configurare alcuni servizi AWS necessari come IAM e S3. Questi verranno configurati utilizzando la console AWS basata sul Web. Tuttavia, la maggior parte della configurazione può essere ottenuta anche utilizzando l'utilità della riga di comando di AWS, che utilizzeremo in seguito.
Creazione di bucket S3
S3 (o Simple Storage Service) è un servizio di archivio oggetti di Amazon che offre un'archiviazione affidabile ed economica di qualsiasi dato. Utilizzeremo S3 per archiviare le immagini che verranno caricate, nonché le versioni ridimensionate delle immagini che abbiamo elaborato.
Il servizio S3 è disponibile nell'elenco a discesa "Servizi" nella console AWS nella sottosezione "Archiviazione e consegna dei contenuti". Quando crei un bucket, ti verrà chiesto di inserire sia il nome del bucket che di selezionare una regione. La selezione di una regione vicina ai tuoi utenti consentirà a S3 di ottimizzare la latenza e i costi, nonché alcuni fattori normativi. Per questo esempio selezioneremo la regione "US Standard". Questa stessa regione verrà successivamente utilizzata per ospitare le funzioni AWS Lambda.
Vale la pena notare che i nomi dei bucket S3 devono essere univoci, quindi se viene preso il nome scelto ti verrà richiesto di scegliere un nuovo nome univoco.
Per questo progetto di esempio, creeremo due bucket di archiviazione denominati "test-upload" e "test-resized". Il bucket "test-upload" verrà utilizzato per caricare le immagini e archiviare l'immagine caricata prima che venga elaborata e ridimensionata. Una volta ridimensionata, l'immagine verrà salvata nel bucket "ridimensionato di prova" e l'immagine grezza caricata verrà rimossa.
Autorizzazioni di caricamento S3
Per impostazione predefinita, le autorizzazioni S3 sono restrittive e non consentono agli utenti esterni o anche agli utenti non amministrativi di leggere, scrivere, aggiornare o eliminare autorizzazioni o oggetti nel bucket. Per modificare questa impostazione, dovremo effettuare l'accesso come utente con i diritti per gestire le autorizzazioni del bucket AWS.
Supponendo di essere sulla console AWS, possiamo visualizzare le autorizzazioni per il nostro bucket di caricamento selezionando il bucket per nome, facendo clic sul pulsante "Proprietà" in alto a destra dello schermo e aprendo la sezione "Autorizzazioni" compressa.
Per consentire agli utenti anonimi di caricare in questo bucket, dovremo modificare la policy del bucket per consentire l'autorizzazione specifica che consente il caricamento. Ciò avviene tramite una policy di configurazione basata su JSON. Questo tipo di policy JSON è ampiamente utilizzato in AWS insieme al servizio IAM. Dopo aver fatto clic sul pulsante "Modifica criterio bucket", incolla semplicemente il testo seguente e fai clic su "Salva" per consentire il caricamento di immagini pubbliche:
{ "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/*" } ] }
Dopo aver eseguito questa operazione, possiamo verificare che la policy del bucket sia corretta tentando di caricare un'immagine nel bucket. Il seguente comando cURL farà il trucco:
curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'
Se viene restituita una risposta di 200 intervalli, sapremo che la configurazione per il bucket di caricamento è stata applicata correttamente. I nostri bucket S3 ora dovrebbero essere (per lo più) configurati. Torneremo in seguito su questo servizio nella console per collegare i nostri eventi di caricamento delle immagini all'invocazione della nostra funzione di ridimensionamento.
Autorizzazioni IAM per Lambda
I ruoli Lambda vengono tutti eseguiti all'interno di un contesto di autorizzazione, in questo caso un "ruolo" definito dal servizio IAM. Questo ruolo definisce tutte le autorizzazioni di cui dispone la funzione Lambda durante la sua chiamata. Ai fini di questo progetto di esempio, creeremo un ruolo generico che verrà utilizzato tra entrambe le funzioni Lambda. Tuttavia, in uno scenario di produzione si consiglia una maggiore granularità nelle definizioni di autorizzazione per garantire che qualsiasi sfruttamento della sicurezza sia isolato solo nel contesto di autorizzazione che è stato definito.
Il servizio IAM è disponibile nella sottosezione "Sicurezza e identità" del menu a discesa "Servizi". Il servizio IAM è uno strumento molto potente per la gestione dell'accesso tra i servizi AWS e l'interfaccia fornita potrebbe essere un po' opprimente all'inizio se non si ha familiarità con strumenti simili.
Una volta nella pagina del dashboard IAM, la sottosezione "Ruoli" si trova sul lato sinistro della pagina. Da qui possiamo utilizzare il pulsante "Crea nuovo ruolo" per visualizzare una procedura guidata in più passaggi per definire le autorizzazioni del ruolo. Usiamo “lambda_role” come nome della nostra autorizzazione generica. Dopo aver proseguito dalla pagina di definizione del nome, ti verrà presentata l'opzione per selezionare un tipo di ruolo. Poiché richiediamo solo l'accesso S3, fai clic su "Ruoli di servizio AWS" e nella casella di selezione seleziona "AWS Lambda". Ti verrà presentata una pagina di politiche che possono essere allegate a questo ruolo. Seleziona la policy "AmazonS3FullAccess" e continua con il passaggio successivo per confermare il ruolo da creare.
È importante annotare il nome e l'ARN (Amazon Resource Name) del ruolo creato. Verrà utilizzato durante la creazione di una nuova funzione Lambda per identificare il ruolo da utilizzare per l'invocazione della funzione.
Nota: AWS Lambda registrerà automaticamente tutto l'output delle chiamate di funzione in AWS Cloudwatch, un servizio di registrazione. Se si desidera questa funzionalità, consigliata per un ambiente di produzione, è necessario aggiungere alle policy per questo ruolo l'autorizzazione a scrivere in un flusso di log di Cloudwatch.
Il codice!
Panoramica
Ora siamo pronti per iniziare a codificare. Assumiamo a questo punto che tu abbia impostato il comando "awscli". In caso contrario, puoi seguire le istruzioni su https://aws.amazon.com/cli/ per configurare awscli sul tuo computer.
Nota: il codice utilizzato in questi esempi è più breve per facilitare la visualizzazione dello schermo. Per una versione più completa, visita il repository all'indirizzo https://github.com/gxx/aws-lambda-python/.
Per prima cosa, impostiamo una struttura a scheletro per il nostro progetto.
aws-lambda-python/ - image_list/ - handler.py - list.html - Makefile - requirements.txt - image_resize/ - handler.py - resize.py - Makefile - requirements.txt - .pydistutils.cfg
Abbiamo due sottodirectory nella nostra struttura, una per ciascuna delle nostre funzioni lambda. In ognuno di questi abbiamo i file handler.py, Makefile e requisiti.txt comuni. Il file handler.py conterrà il metodo per richiamare l'invocazione di ciascuna delle funzioni lambda e può essere considerato il punto di ingresso per le funzioni. Il file Requirements.txt conterrà un elenco delle nostre dipendenze, in modo da poter specificare e aggiornare facilmente i requisiti. Infine, il comando Makefile che useremo per fornire un facile meccanismo per interagire con awscli. Ciò renderà molto più semplice il processo di creazione e aggiornamento della nostra funzione lambda.
Noterai il file .pydistutils.cfg nella radice della nostra directory del progetto. Questo file è necessario se stai lavorando con Python in Homebrew. A causa del metodo di distribuzione di una funzione Lambda (trattato nella sezione seguente), questo file è necessario. Vedere il repository per maggiori dettagli.
Ridimensiona la funzione Lambda dell'immagine
Codice
A partire dalla funzione resize_image, congeleremo la dipendenza di Wand, la nostra libreria di elaborazione delle immagini, salvando Wand==0.4.2
su Requirements.txt. Questa sarà l'unica dipendenza per la nostra funzione lambda image_resize. La funzione resize_image in resize.py dovrà gestire una risorsa immagine dalla libreria Wand e ridimensionarla in base ai parametri di larghezza e altezza specificati. Per preservare l'immagine che viene ridimensionata, utilizzeremo un algoritmo di ridimensionamento "più adatto" che manterrà il rapporto dell'immagine dell'immagine originale, riducendo al contempo le dimensioni dell'immagine per adattarle alla larghezza e all'altezza specificate.
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
Detto questo, è necessaria una funzione di gestione per accettare l'evento generato da un'immagine S3 caricata, passarlo alla funzione resize_image
e salvare l'immagine ridimensionata risultante.

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()
Distribuzione
Una volta completato il codice, dovrà essere caricato su Amazon Lambda come nuova funzione Lambda. È qui che entra in gioco il Makefile che è stato aggiunto alla struttura della directory. Questo Makefile verrà utilizzato per distribuire le definizioni della funzione Lambda che stiamo creando.
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
Le funzioni principali di questo Makefile sono “crea” e “aggiorna”. Queste funzioni prima impacchettano la directory corrente, che rappresenta tutto il codice necessario per eseguire la funzione Lambda. Successivamente, tutte le dipendenze specificate nel file requirements.txt
verranno installate nella sottodirectory corrente da impacchettare. La fase di confezionamento comprime il contenuto della directory da caricare successivamente con il comando “awscli”. Il nostro Makefile può essere adattato per l'uso nell'altra definizione di funzione Lambda.
Nell'utility Makefile, definiamo alcune variabili necessarie per creare/aggiornare la nostra immagine. Configurali come necessario affinché i comandi Makefile funzionino correttamente per te.
-
ROLE_ARN
: questo è l'Amazon Resource Name che identifica il nostro ruolo in base al quale eseguire la funzione Lambda. -
FUNCTION_NAME
: il nome della funzione Lambda che stiamo creando/aggiornando. -
REGION
: la regione in cui verrà creata/aggiornata la funzione Lambda. -
TIMEOUT
: Timeout in secondi prima che un'invocazione Lambda venga uccisa. -
MEMORY_SIZE
: dimensione della memoria in megabyte a cui la funzione Lambda avrà accesso quando viene richiamata. -
ZIPFILE_NAME
: il nome del pacchetto compresso contenente il codice della funzione Lambda e le dipendenze. -
HANDLER
: Il percorso di importazione assoluto, in notazione punto, della funzione handler.
Una volta configurato, l'esecuzione del comando make create
genererà qualcosa di simile al seguente output:
$ 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": "" }
Test
Dopo aver eseguito il comando di creazione, la funzione di ridimensionamento delle nostre immagini è disponibile per essere utilizzata, tuttavia non è stata collegata al bucket S3 per ricevere gli eventi. Possiamo ancora testare la funzione tramite la Console AWS per affermare che la funzione gestisce correttamente gli eventi di caricamento dei file S3. Nella dashboard di AWS Lambda, che puoi trovare nella sottosezione "Calcola" del menu a discesa "Servizi", seleziona il nome della funzione che abbiamo creato. Questa pagina dei dettagli della funzione Lambda fornisce un elenco a discesa denominato "Azioni" contenente un'opzione denominata "Configura evento di test".
Facendo clic su questo si aprirà una modale che consente di specificare un evento di test e alcuni modelli di esempio. Scegli l'esempio "S3 Put" e sostituisci qualsiasi menzione del nome di un bucket con il nome del bucket che è stato impostato. Una volta che questa è stata configurata, il successivo utilizzo del pulsante "Test" nella pagina della funzione Lambda invocherà la funzione Lambda come se l'evento precedentemente configurato si fosse realmente verificato.
Per monitorare eventuali tracce di stack di errori o messaggi di registro, puoi visualizzare il flusso di registro in Cloudwatch. Un nuovo gruppo di log sarà stato creato contemporaneamente alla creazione della funzione Lambda. Questi flussi di log sono utili e possono essere reindirizzati ad altri servizi.
Connessione agli eventi del bucket S3
Di nuovo nella dashboard di S3, espandi la sezione "Eventi" compressa situata nel menu "Proprietà" per mostrare il modulo "Notifiche di eventi". I campi obbligatori da compilare sono gli input "Eventi" e "Invia a". Da "Eventi", seleziona l'evento "Oggetto creato (tutto)". Ciò consentirà l'intercettazione di tutti gli eventi che creano un oggetto nel bucket di caricamento. Per l'ingresso "Inviato a", selezionare il pulsante di opzione "Funzione Lambda". Apparirà una nuova sezione con un menu a tendina contenente la funzione lambda “ResizeImage” che abbiamo configurato come opzione. Facendo clic su "Salva", tutti gli eventi "Oggetto creato" verranno ora indirizzati come input per l'invocazione della funzione Lambda "ResizeImage".
Ora abbiamo la funzionalità principale dell'applicazione. Eseguiamo un altro test cURL per assicurarci che tutto funzioni come previsto. Utilizza cURL per caricare un'immagine nel bucket S3 e verifica manualmente che l'immagine sia stata caricata nel bucket di ridimensionamento.
curl https://test-upload.s3.amazonaws.com -F 'key=test.jpeg' -F '[email protected]'
Dopo aver eseguito questo comando, l'immagine ridimensionata deve essere creata nel bucket "ridimensionato di prova" dopo 50-1000 ms, a seconda che la funzione Lambda sia già stata "riscaldata".
Elenca la funzione Lambda dell'immagine
Codice
La funzione ListImage Lambda recupererà un elenco di immagini ridimensionate e le visualizzerà su una pagina HTML per l'utente. Questa pagina HTML fornisce anche la funzionalità per l'utente di caricare le proprie immagini. Jinja2 viene utilizzato nella funzione per eseguire il rendering di HTML da una definizione di modello. Proprio come prima, questi requirements.txt
sono specificati nel file Requirements.txt.
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>
Ancora una volta, possiamo modificare il Makefile precedente e utilizzare il comando create per distribuire la nostra funzione lambda.
Gateway API
La funzione Lambda ImageList è completa, tuttavia non può essere servita a nessun utente. Questo perché le funzioni Lambda possono essere chiamate solo in risposta a un evento da un altro servizio o a livello di codice. È qui che entra in gioco il servizio Amazon AWS API Gateway. API Gateway è disponibile nella sottosezione "Servizi applicativi".
API Gateway è un modo per modellare gli endpoint come un insieme di risorse e metodi, essenzialmente un'interfaccia REST. Oltre a fornire una struttura per la convalida e la trasformazione delle richieste, API Gateway esegue altre funzioni come la fornitura di richieste di limitazione della velocità/limitazione della velocità.
Dal dashboard di API Gateway, crea una nuova API per servire la funzione ListImage. Il nome e la descrizione possono essere impostati secondo le tue preferenze. Una volta creata, clicca sul nome della nuova API per accedere ai dettagli dell'API. Crea una nuova risorsa per l'URL radice "/". Questo URL verrà utilizzato per servire la pagina HTML.
Durante la visualizzazione dei dettagli per la pagina delle risorse radice, aggiungi un metodo GET. Imposta il "Tipo di integrazione" su "Funzione Lambda", imposta "Regione Lambda" su "us-west-1" o la regione selezionata e digita il nome della funzione ListImage Lambda.
Prima di poter iniziare a mappare la nostra risposta a un output HTML, dobbiamo definire un "modello" che definirà uno schema per la risposta dal server oltre a mappare questa risposta a un tipo di contenuto. Seleziona la sezione "Modelli" per l'API e fai clic su "Crea" per creare un nuovo modello. Assegna al modello il nome “HTML”, con un tipo di contenuto “text/html” e definisci lo schema come segue:
{ "$schema": "http://json-schema.org/draft-04/schema#", "title" : "HTML", "type" : "object" }
Di nuovo sulla dashboard dell'API, seleziona la risorsa che abbiamo creato e vai alla sezione "Risposta di integrazione". Questa sezione definisce qualsiasi trasformazione da elaborare dopo aver ricevuto una risposta dalla funzione Lambda prima di reindirizzare la risposta al passaggio finale.
Apri la sezione "Modelli di mappatura" e aggiungi un nuovo "Tipo di contenuto" di "testo/html". Rimuovi contemporaneamente il vecchio "Tipo di contenuto". Sulla destra, cambia il menu a discesa da "Output Passthrough" a "Mapping template". Ciò ci consentirà di modificare il JSON grezzo accettato da API Gateway e utilizzare invece il contenuto HTML all'interno della proprietà "htmlContent" dei nostri dati restituiti. Per il modello di mappatura, specifica "$input.htmlContent" come modello. Infine, modifica la sezione "Risposta metodo" rimuovendo "applicazione/json" da "Modelli di risposta per 200" e aggiungendo invece "testo/html".
Tornando alla dashboard per l'API, c'è un pulsante in alto a sinistra della pagina con l'etichetta "Distribuisci API". Fare clic su questo pulsante per aggiornare o creare l'API con le risorse, i metodi, i modelli e le mappature specificati. Al termine, verrà visualizzato un URL per la fase di distribuzione selezionata (staging per impostazione predefinita). Finalmente l'esempio è completo! Puoi caricare alcuni file per testare e visualizzare le immagini ridimensionate.
Avvolgendo
AWS è un servizio di grandi dimensioni e non scomparirà presto. Sebbene il vendor lock-in sia sempre qualcosa a cui prestare attenzione, AWS Lambda offre un servizio relativamente sottile con un ricco set di opzioni di configurazione ausiliarie. Sfruttare i servizi forniti da AWS per implementare applicazioni facilmente scalabili e gestibili offrirà il massimo vantaggio dell'utilizzo della piattaforma AWS. AWS Lambda offre una soluzione elegante, scalabile ed economica supportata da una piattaforma di livello aziendale utilizzata da un numero molto elevato di consumatori. Credo che le applicazioni "serverless" siano la via del futuro. Facci sapere cosa ne pensi nei commenti qui sotto.