Elaborazione serverless con AWS Lambda, parte 1

Il serverless computing potrebbe essere la cosa più calda nel cloud computing oggi, ma di cosa si tratta esattamente? Questo tutorial in due parti inizia con una panoramica dell'elaborazione serverless: da cosa è, al motivo per cui è considerato dirompente per il cloud computing tradizionale e come potresti usarlo nella programmazione basata su Java.

Dopo la panoramica, riceverai un'introduzione pratica ad AWS Lambda, che oggi è considerata da molti la prima soluzione basata su Java per l'elaborazione serverless. Nella parte 1, utilizzerai AWS Lambda per creare, distribuire e testare la tua prima funzione Lambda in Java. Nella parte 2, integrerai la tua funzione Lambda con DynamoDB, quindi utilizzerai l'SDK AWS per richiamare le funzioni Lambda in un'applicazione Java.

Cos'è il serverless computing?

L'anno scorso stavo parlando con uno stagista dell'azienda di diversi modelli architettonici e menzionavo l'architettura serverless. Ha subito notato che tutte le applicazioni richiedono un server e non possono essere eseguite sul nulla. Lo stagista aveva ragione, anche se gli mancava il mio. Il serverless computing non è una piattaforma magica per l'esecuzione di applicazioni.

In effetti, l' elaborazione senza server significa semplicemente che tu, lo sviluppatore, non devi occuparti del server. Una piattaforma di elaborazione serverless come AWS Lambda ti consente di creare il tuo codice e distribuirlo senza mai dover configurare o gestire i server sottostanti. La tua unità di distribuzione è il tuo codice; non il contenitore che ospita il codice o il server che esegue il codice, ma semplicemente il codice stesso. Dal punto di vista della produttività, ci sono evidenti vantaggi nell'offload dei dettagli di dove è archiviato il codice e di come viene gestito l'ambiente di esecuzione. Anche il calcolo serverless ha un prezzo basato su metriche di esecuzione, quindi c'è anche un vantaggio finanziario.

Quanto costa AWS Lambda?

Al momento della stesura di questo documento, il livello di prezzo di AWS Lambda si basa sul numero di esecuzioni e sulla durata dell'esecuzione:

  • Il tuo primo milione di esecuzioni al mese è gratuito, successivamente paghi $ 0,20 per milione di esecuzioni ($ 0,0000002 per richiesta).
  • La durata viene calcolata dal momento in cui il codice inizia l'esecuzione fino a quando non restituisce un risultato, arrotondato ai 100 ms più vicini. L'importo addebitato si basa sulla quantità di RAM allocata alla funzione, dove il costo è di $ 0,00001667 per ogni GB al secondo.

I dettagli sui prezzi e le allocazioni del livello gratuito sono leggermente più complicati di quanto implichi la panoramica. Visita la fascia di prezzo per esaminare alcuni scenari di prezzo.

Per avere un'idea di come funziona il calcolo senza server, iniziamo con il modello di esecuzione del calcolo senza server, che è illustrato nella Figura 1.

Steven Haines

Ecco il modello di esecuzione senza server in poche parole:

  1. Un client effettua una richiesta alla piattaforma informatica senza server per eseguire una funzione specifica.
  2. La piattaforma di elaborazione senza server verifica prima se la funzione è in esecuzione su uno dei suoi server. Se la funzione non è già in esecuzione, la piattaforma carica la funzione da un archivio dati.
  3. La piattaforma quindi distribuisce la funzione a uno dei suoi server, che sono preconfigurati con un ambiente di esecuzione in grado di eseguire la funzione.
  4. Esegue la funzione e acquisisce il risultato.
  5. Restituisce il risultato al client.

A volte l'elaborazione serverless è chiamata Function as a Service (FaaS), perché la granularità del codice che si crea è una funzione . La piattaforma esegue la funzione sul proprio server e orchestra il processo tra le richieste di funzione e le risposte della funzione.

Nanoservizi, scalabilità e prezzo

Tre cose contano davvero nell'elaborazione senza server: la sua architettura di nanoservizi; il fatto che sia praticamente infinitamente scalabile; e il modello di prezzo associato a quella scalabilità quasi infinita. Approfondiremo ciascuno di questi fattori.

Nanoservizi

Hai sentito parlare di microservizi e probabilmente conosci le applicazioni a 12 fattori, ma le funzioni serverless portano il paradigma della scomposizione di un componente nelle sue parti costituenti a un livello completamente nuovo. Il termine "nanoservizi" non è un termine riconosciuto dal settore, ma l'idea è semplice: ogni nanoservizio dovrebbe implementare una singola azione o responsabilità. Ad esempio, se si volesse creare un widget, l'atto di creazione sarebbe il proprio nanoservizio; se si volesse recuperare un widget, anche l'atto di recupero sarebbe un nanoservizio; e se volessi effettuare un ordine per un widget, quell'ordine sarebbe ancora un altro nanoservizio.

Un'architettura di nanoservizi ti consente di definire la tua applicazione a un livello molto fine. Simile allo sviluppo basato sui test (che ti aiuta a evitare effetti collaterali indesiderati scrivendo il tuo codice a livello di test individuali), un'architettura di nanoservizi incoraggia la definizione della tua applicazione in termini di funzioni molto dettagliate e specifiche. Questo approccio aumenta la chiarezza su ciò che stai creando e riduce gli effetti collaterali indesiderati del nuovo codice.

Microservizi vs nanoservizi

I microservizi ci incoraggiano a suddividere un'applicazione in una raccolta di servizi che svolgono ciascuno un compito specifico. La sfida è che nessuno ha realmente quantificato l' ambito di un microservizio. Di conseguenza, finiamo per definire i microservizi come una raccolta di servizi correlati, che interagiscono tutti con lo stesso modello di dati. Concettualmente, se si dispone di funzionalità di basso livello che interagiscono con un dato modello di dati, la funzionalità dovrebbe entrare in uno dei servizi correlati. Le interazioni di alto livello dovrebbero effettuare chiamate al servizio anziché interrogare direttamente il database.

È in corso un dibattito nell'elaborazione serverless sull'opportunità di creare funzioni Lambda a livello di microservizi o nanoservizi. La buona notizia è che puoi creare facilmente le tue funzioni con entrambe le granularità, ma una strategia per i microservizi richiederà un po 'di logica di routing extra nel gestore delle richieste.

Dal punto di vista del design, le applicazioni serverless dovrebbero essere molto ben definite e pulite. Dal punto di vista della distribuzione, sarà necessario gestire molte più distribuzioni, ma si avrà anche la possibilità di distribuire le nuove versioni delle funzioni individualmente, senza influire su altre funzioni. L'elaborazione serverless è particolarmente adatta allo sviluppo in team di grandi dimensioni, dove può contribuire a rendere il processo di sviluppo più semplice e il codice meno soggetto a errori.

Scalabilità

Oltre a introdurre un nuovo paradigma architettonico, le piattaforme di elaborazione serverless forniscono una scalabilità praticamente infinita. Dico "praticamente" perché non esiste veramentescalabilità infinita. Per tutti gli scopi pratici, tuttavia, i provider di elaborazione serverless come Amazon possono gestire più carico di quello che potresti eventualmente gettare loro. Se dovessi gestire la scalabilità dei tuoi server (o macchine virtuali basate su cloud) per soddisfare la crescente domanda, dovresti monitorare l'utilizzo, identificare quando avviare più server e aggiungere più server al tuo cluster al momento giusto. Allo stesso modo, quando la domanda è diminuita, è necessario ridimensionare manualmente. Con l'elaborazione serverless, comunichi alla tua piattaforma di elaborazione serverless il numero massimo di richieste di funzioni simultanee che desideri eseguire e la piattaforma esegue il ridimensionamento per te.

Prezzi

Infine, il modello di prezzo del calcolo senza server consente di scalare la bolletta del cloud in base all'utilizzo. Quando hai un utilizzo leggero, la bolletta sarà bassa (o nulla se rimani nel range libero). Ovviamente, la tua bolletta aumenterà con l'utilizzo, ma si spera che avrai anche nuove entrate per supportare la tua bolletta cloud più elevata. Al contrario, se dovessi gestire i tuoi server, dovresti pagare un costo base per eseguire il numero minimo di server richiesto. Con l'aumentare dell'utilizzo, aumenterai la scalabilità in incrementi di interi server, anziché in incrementi di singole chiamate di funzione. Il modello di prezzo del calcolo senza server è direttamente proporzionale al tuo utilizzo.

AWS Lambda per l'elaborazione serverless

AWS Lambda è una piattaforma di elaborazione serverless implementata su piattaforme Amazon Web Services come EC2 e S3. AWS Lambda crittografa e archivia il codice in S3. Quando viene richiesta l'esecuzione di una funzione, crea un "contenitore" utilizzando le specifiche di runtime, lo distribuisce a una delle istanze EC2 nella sua compute farm ed esegue quella funzione. Il processo è mostrato nella Figura 2.

Steven Haines

When you create a Lambda function, you configure it in AWS Lambda, specifying things like the runtime environment (we'll use Java 8 for this article), how much memory to allocate to it, identity and access management roles, and the method to execute. AWS Lambda uses your configuration to setup a container and deploy the container to an EC2 instance. It then executes the method that you've specified, in the order of package, class, and method.

At the time of this writing, you can build Lambda functions in Node, Java, Python, and most recently, C#. For the purposes of this article we will use Java.

What is a Lambda function?

When you write code designed to run in AWS Lambda, you are writing functions. The term functions comes from functional programming, which originated in lambda calculus. The basic idea is to compose an application as a collection of functions, which are methods that accept arguments, compute a result, and have no unwanted side-effects. Functional programming takes a mathematical approach to writing code that can be proven to be correct. While it's good to keep functional programming in mind when you are writing code for AWS Lambda, all you really need to understand is that the function is a single-method entry-point that accepts an input object and returns an output object.

Serverless execution modes

While Lambda functions can run synchronously, as described above, they can also run asynchronously and in response to events. For example, you could configure a Lambda to run whenever a file was uploaded to an S3 bucket. This configuration is sometimes used for image or video processing: when a new image is uploaded to an S3 bucket, a Lambda function is invoked with a reference to the image to process it.

I worked with a very large company that leveraged this solution for photographers covering a marathon. The photographers were on the course taking photographs. Once their memory cards were full, they loaded the images onto a laptop and uploaded the files to S3. As images were uploaded, Lambda functions were executed to resize, watermark, and add a reference for each image to its runner in the database.

All of this would take a lot of work to accomplish manually, but in this case the work not only processed faster because of AWS Lambda's horizontal scalability, but also seamlessly scaled up and back down, thus optimizing the company's cloud bill.

In addition to responding to files uploaded to S3, lambdas can be triggered by other sources, such as records being inserted into a DynamoDB database and analytic information streaming from Amazon Kinesis. We'll look at an example featuring DynamoDB in Part 2.

AWS Lambda functions in Java

Now that you know a little bit about serverless computing and AWS Lambda, I'lll walk you through building an AWS Lambda function in Java. 

download Ottieni il codice Codice sorgente per l'applicazione di esempio per questo tutorial, "Elaborazione senza server con AWS Lambda". Creato da Steven Haines per JavaWorld.

Implementazione di funzioni Lambda

Puoi scrivere una funzione Lambda in due modi:

  • La funzione può ricevere un flusso di input al client e scrivere in un flusso di output al client.
  • La funzione può utilizzare un'interfaccia predefinita, nel qual caso AWS Lambda deserializzerà automaticamente il flusso di input a un oggetto, lo passerà alla funzione e serializzerà la risposta della funzione prima di restituirla al client.

Il modo più semplice per implementare una funzione AWS Lambda è utilizzare un'interfaccia predefinita. Per Java, devi prima includere la seguente libreria di base AWS Lambda nel tuo progetto (tieni presente che questo esempio utilizza Maven):

 com.amazonaws aws-lambda-java-core 1.1.0  

Next, have your class implement the following interface:

Listing 1. RequestHandler.java

 public interface RequestHandler { /** * Handles a Lambda function request * @param input The Lambda function input * @param context The Lambda execution environment context object. * @return The Lambda function output */ public O handleRequest(I input, Context context); } 

The RequestHandler interface defines a single method: handleRequest(), which is passed an input object and a Context object, and returns an output object. For example, if you were to define a Request class and a Response class, you could implement your lambda as follows:

 public class MyHandler implements RequestHandler { public Response handleRequest(Request request, Context context) { ... } } 

Alternatively, if you wanted to bypass the predefined interface, you could manually handle the InputStream and OutputStream yourself, by implementing a method with the following signature:

 public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException { ... } 

The Context object provides information about your function and the environment in which it is running, such as the function name, its memory limit, its logger, and the amount of time remaining, in milliseconds, that the function has to complete before AWS Lambda kills it.