AWS Serverless – The million dollar homepage
La "The Million Dollar Homepage" è una delle pagine che ha fatto la storia di Internet e del Web: un sito composto da una semplice immagine, suddivisa in un milione di blocchi da vendere ciascuno ad un solo, onesto, dollaro. Ne conosciamo tutti il seguito e l'enorme successo.
Immaginiamo, per qualche minuto, di chiamarci Alex Tew, di essere uno studente universitario inglese e di dover necessariamente trovare un modo per finanziarci gli studi. Improvvisamente boom! Un'idea!
Se fossimo nel 2005, anno in cui Alex realizza e pubblica "The Million Dollar Homepage", non potremmo appoggiarci ai servizi cloud di Amazon in quanto AWS verrà fondata l'anno successivo. Pur tenendo conto della semplicità del progetto, dovremo obbligatoriamente occuparci di tutte le attività di gestione dell'infrastruttura come il provisioning del server o del cluster, l'applicazione di patch e la manutenzione del sistema operativo.
Fortunatamente siamo invece nel 2019 e abbiamo un ecosistema di soluzioni serverless che AWS ci mette a disposizione. Come realizzare la stessa pagina da un milione di dollari in modo agile e economico?
In questo articolo proveremo per gioco a identificare le soluzioni serverless che fanno al caso nostro e definiremo l'architettura della nostra webpage: che ci serva come esercizio per approfondire la conoscenza dei building block di AWS.
Prima però un piccolo chiarimento: quando si parla di paradigma serverless non significa che non ci siano server a supporto dei servizi che andremo ad utilizzare, ovviamente. Semplicemente non ne percepiamo la presenza e non ci è richiesto di occuparcene.
Requisiti
Iniziamo col fare una lista delle funzionalità della nostra web app:
- Dovremo visualizzare il banner "da un milione di dollari", composto dalle immagini scelte dai clienti e dai rimanenti spazi liberi disponibili per l'acquisto
- Daremo la possibilità di acquistare uno degli spazio liberi: l'acquirente dovrà registrarsi sul sito e procedere al pagamento per lo spazio scelto.
- Confermato il pagamento, l'acquirente potrà procedere all'upload dell'immagine scelta che verrà collocata nello spazio libero acquistato. Dovrà inoltre indicare il proprio slogan e l'URL di riferimento
- Vogliamo che la nostra web app sia pronta a scalare per poter rispondere in tempi rapidi alle richieste di visualizzazione di migliaia di utenti sparsi per il mondo
Vedremo nelle prossime sezioni come implementare, step by step, i componenti della nostra soluzione.
Inizio easy
Decidiamo come prima versione del sito di pubblicare esclusivamente contenuti statici.
Avremo una o più pagine HTML, CSS, JS e ovviamente immagini tra le quali il nostro banner milionario.
Abbiamo bisogno di istanziare un server web? Assolutamente no. Utilizziamo Amazon S3.
Amazon S3 è il servizio di storage di oggetti che offre scalabilità, disponibilità dei dati, sicurezza e prestazioni.
Creiamo un bucket dove collocare i nostri file, abilitiamo la proprietà "hosting siti web statici" e creiamo una bucket policy per consentire l'accesso pubblico in sola lettura.
Finito, siamo online! Se vogliamo essere originali e abbiamo registrato un dominio internet per la nostra applicazione, ci basterà configurare un record CNAME nella relativa zona DNS per poterlo utilizzare e "mascherare" l'endpoint HTTP S3. Attenzione: in questo caso il nome del bucket dovrà corrispondere al record CNAME.
Automatizziamo
Diciamo che il nostro sito inizia ad essere conosciuto. I clienti ci contattano via email per acquistare uno spazio libero e noi dobbiamo fornirgli le informazioni per effettuare il pagamento. Una volta verificato il pagamento e ottenuta l'immagine del cliente, la andiamo ad applicare alla million dollars page. Infine pubblichiamo la nuova pagina del sito. Purtroppo abbiamo anche garantito al nostro cliente di poter cambiare la propria immagine tutte le volte che lo desidera, quindi il processo si ripete più volte al giorno per diversi clienti. Ci rendiamo conto di non riuscire a gestire "manualmente" tutte queste operazioni e decidiamo che è venuto il momento di automatizzare.
Per prima cosa dovremo essere in grado di gestire gli ordini dei clienti.
E' il momento di introdurre un pò di elementi: ci viene in aiuto Cognito.
Amazon Cognito permette di aggiungere strumenti di registrazione, accesso e controllo degli accessi alle app Web integrandosi con provider di identità social quali Facebook e Google.
Possiamo quindi gestire semplicemente tutto il processo di registrazione, login, logout e recupero password dei nostri clienti. A questi andremo a fornire una form per l'acquisto di uno spazio. Come realizziamo il backend?
Andremo ad introdurre l'Amazon API Gateway come elemento esposto su internet e collegheremo gli endpoint Lambda in grado di processare l'ordine e salvarlo su un database.
Amazon API Gateway semplifica la creazione, la pubblicazione e la manutenzione delle proprie API.
Amazon Lambda consente di eseguire codice senza dover effettuare il provisioning e gestione di un server.
Quale database? Se vogliamo rimanere serverless (e certo che si!) abbiamo due possibilità: DynamoDB o Aurora Serverless. Preferiamo NoSQL e scegliamo quindi DynamoDB.
DynamoDB è un database non relazionale completamente gestito per applicazioni che necessitano di prestazioni elevate su qualsiasi scala.
Ok, come si presenta ora l'architettura della nostra soluzione? Vediamola.
Abbiamo aggiunto quindi la possibilità di inserire un ordine. Al termine dell'inserimento mostreremo al nostro cliente la pagina per il pagamento dello stesso. Ipotizziamo, per rapidità, di usare PayPal. Ci servirà una API per poter verificare la transazione tramite l'endpoint di PayPal al termine del processo di pagamento: andremo quindi a realizzare un'altra Lambda function per questo scopo che, una volta verificato, cambierà lo stato dell'ordine in "Pagato".
A questo punto tutto il processo di invio dell'ordine e pagamento è automatizzato. Per comodità vogliamo ricevere una notifica email ad avvenuto pagamento di un ordine, con tutti i dettagli dello stesso e l'indirizzo a cui poter contattare il nostro acquirente. Per questo motivo ho aggiunto il servizio SES (Simple Email Service) alla nostra architettura, che sarà richiamato direttamente dalla nostra Lambda function.
Amazon SES è un servizio di invio di e-mail basato sul cloud progettato per consentire agli esperti di marketing e agli sviluppatori di applicazioni di inviare e-mail di marketing, notifiche ed e-mail transazionali.
Sebbene una buona parte del lavoro sia stata fatta ci rimane ancora un passo da automatizzare: dare la possibilità al nostro cliente di aggiornare direttamente la propria immagine che andrà a far parte del nostro collage milionario.
Upload dell'immagine
Dobbiamo dare al nostro cliente la possibilità di effettuare in qualunque momento l'upload di un'immagine, che andrà ad occupare lo spazio precedentemente acquistato sul nostro million dollar banner. Il nostro bucket S3 è accessibile pubblicamente in sola lettura, ovviamente. Come possiamo autorizzare e gestire l'upload di un file per un utente specifico?
Ci viene in aiuto una funzionalità di S3 chiamata "presigned URL": andiamo a generare una URL temporanea (con scadenza) che il client potrà utilizzare per effettuare l'upload di un file nel nostro bucket senza dover fornire allo stesso altre credenziali di accesso o ruoli specifici.
Useremo una funzione Lambda anche in questo caso. Questa si occuperà di richiedere la presigned URL al servizio S3, ma solo dopo aver verificato che l'utente abbia effettivamente acquisto una spazio del nostro banner. Ottenuta l'URL, verrà restituita al client per procedere al upload.
Finito? Non ancora. L'immagine scelta dal cliente è ora nel nostro bucket. Come possiamo prenderla in carico, ridimensionarla e rigenerare il nostro banner includendo questa nuova immagine nella posizione corretta? La risposta è ancora una funzione Lambda che sarà triggerata direttamente dal servizio S3 ogni qualvolta viene effettuato l'upload di una nuova immagine.
Ecco il quadro completo.
Conclusioni
Andiamo ad analizzare la nostra architettura: abbiamo utilizzato esclusivamente servizi serverless, semplici da manutenere e con costi sensibilmente ridotti rispetto ad una soluzione "classica", in quanto non ci è richiesto un provisioning iniziale della capacità. I costi sono trasparenti e in base all'utilizzo. Non ci dovremo preoccupare di gestire server e sistemi operativi. Non dovremo nemmeno occuparci di scalare i componenti della nostra architettura in caso di grande successo, molte visualizzazioni, molti clienti che frequentemente aggiornano la propria immagine: questo perché i servizi utilizzati scalano (o possono essere configurati per scalare) automaticamente. Security e affidabilità? Anche questi in carico a Amazon. Potremo semplicemente concentrarci sulla nostra applicazione senza preoccuparci dell'intera infrastruttura che la supporta.
Non male vero?
Abbiamo inoltre qualche altro asso nella manica: potremo monitorare la nostra soluzione grazie ad Amazon CloudWatch, includendo metriche e log.
Amazon CloudWatch è un servizio di monitoraggio e osservabilità. Fornisce dati e analisi concrete per monitorare le applicazioni e rispondere ai cambiamenti di prestazioni a livello di sistema.
Potremo decidere di abilitare l'encryption "at rest" sia su S3 che su DynamoDB e utilizzare VPC private. Potremmo decidere di utilizzare Amazon CloudFront come front-end del servizio S3, distribuendo la nostra applicazione sulle 200 edge location di AWS.
Amazon CloudFront è una rete per la distribuzione rapida di contenuti o CDN (Content Delivery Network) che permette la distribuzione di dati, video, applicazioni e API a livello globale agli utenti con latenza minima, velocità di trasferimento elevata.
Ci siamo divertiti? Alla prossima!