Funzioni serverless con la funzione Spring Cloud

1. Introduzione

In questo tutorial impareremo come utilizzare la funzione Spring Cloud.

Creeremo ed eseguiremo una semplice funzione Spring Cloud localmente e poi la distribuiremo in AWS.

2. Configurazione della funzione Spring Cloud

Per cominciare, implementiamo da zero e testiamo un semplice progetto con due funzioni utilizzando approcci diversi:

  • Un invertitore di stringa, utilizzando un metodo semplice
  • E un saluto che utilizza una classe dedicata

2.1. Dipendenze di Maven

La prima cosa che dobbiamo fare è includere la dipendenza spring-cloud-starter-funzione-web . Questo fungerà da adattatore locale e porterà le dipendenze necessarie per eseguire la nostra funzione localmente:

 org.springframework.cloud spring-cloud-starter-function-web 1.0.1.RELEASE 

Resta sintonizzato perché lo modificheremo un po 'durante la distribuzione in AWS.

2.2. Scrittura della funzione Spring Cloud

Con Spring Cloud Function, possiamo esporre @Bean di tipo Function , Consumer o Supplier come metodi individuali :

@SpringBootApplication public class CloudFunctionApplication { public static void main(String[] args) { SpringApplication.run(CloudFunctionApplication.class, args); } @Bean public Function reverseString() { return value -> new StringBuilder(value).reverse().toString(); } }

Come in questo codice, possiamo esporre una funzione di stringa inversa come una funzione , che la nostra piattaforma funzionale di destinazione può richiamare.

2.3. Verifica locale della funzione stringa inversa

La funzione spring-cloud-starter-web espone la funzione come endpoint HTTP. Dopo aver eseguito CloudFunctionApplication , possiamo arricciare il nostro target per testarlo localmente:

curl localhost:8080/reverseString -H "Content-Type: text/plain" -d "Baeldung User"

Notare che l'endpoint è il nome del bean.

E come previsto, otteniamo la stringa invertita come output:

resU gnudleaB

2.4. Scansione della funzione Spring Cloud nei pacchetti

Oltre a esporre il nostro metodo come @Bean, potremmo anche scrivere il nostro software come classi che implementano l'interfaccia funzionale Funzione :

public class Greeter implements Function { @Override public String apply(String s) { return "Hello " + s + ", and welcome to Spring Cloud Function!!!"; } }

Possiamo quindi specificare i pacchetti da scansionare per i bean rilevanti in application.properties :

spring.cloud.function.scan.packages=com.baeldung.spring.cloudfunction.functions

2.5. Testare la funzione Greeter in locale

Di nuovo, possiamo avviare l'app e utilizzare curl per testare la funzione Greeter :

curl localhost:8080/greeter -H "Content-Type: text/plain" -d "World"

Notare che l'endpoint è il nome della classe che implementa l'interfaccia funzionale.

E, nessuna sorpresa, riceviamo indietro il saluto atteso:

Hello World, and welcome to Spring Cloud function!!!

3. Funzione Spring Cloud su AWS

Ciò che rende la funzione Spring Cloud così potente è che possiamo creare funzioni abilitate per Spring che sono indipendenti dal cloud. La funzione stessa non ha bisogno di sapere come è stata chiamata o l'ambiente in cui è distribuita. Ad esempio, possiamo facilmente distribuire questo messaggio di benvenuto su AWS, Azure o la piattaforma Google Cloud senza modificare alcuna logica di business.

Poiché AWS Lambda è una delle popolari soluzioni serverless, concentriamoci su come distribuire la nostra app al suo interno.

Quindi, non aspettiamo oltre e distribuiamo la nostra funzione nel cloud!

3.1. Dipendenze di Maven

Ricorda la dipendenza spring-cloud-starter-funzione-web , che abbiamo aggiunto in origine. Ora è il momento di cambiare la situazione.

Vedi, a seconda di dove eseguiremo la funzione Spring Cloud, dobbiamo aggiungere la dipendenza appropriata.

Per AWS, utilizzeremo spring-cloud-function-adapter-aws :

 org.springframework.cloud spring-cloud-function-adapter-aws 

Successivamente, aggiungiamo le dipendenze AWS richieste per gestire gli eventi Lambda:

 com.amazonaws aws-lambda-java-events 2.0.2 provided   com.amazonaws aws-lambda-java-core 1.1.0 provided 

Infine, poiché caricheremo l'artefatto generato dalla build Maven su AWS Lambda, dobbiamo creare un artefatto ombreggiato, ovvero tutte le dipendenze sono esplose come singoli file di classe anziché come jar.

La dipendenza spring-boot-thin-layout ci aiuta a ridurre la dimensione del manufatto escludendo alcune dipendenze che non sono necessarie:

   org.apache.maven.plugins maven-deploy-plugin  true    org.springframework.boot spring-boot-maven-plugin   org.springframework.boot.experimental spring-boot-thin-layout 1.0.10.RELEASE     org.apache.maven.plugins maven-shade-plugin  false true aws    

3.2. Gestori AWS

If we want to expose our string reverser again via an HTTP request, then Spring Cloud Function AWS ships with SpringBootRequestHandler. It implements AWS's RequestHandler and is in charge of dispatching the AWS request to our function.

public class MyStringHandlers extends SpringBootRequestHandler { }

Spring Cloud Function AWS also ships with SpringBootStreamHandler and FunctionInvokingS3EventHandler as other examples

Now, it may seem a bit odd that the MyStringHandlers is just an empty class but it plays an important role in both acting as the entry point of the Lambda function and also defining its input and output types.

As we'll see in the screenshot below, we'll provide the fully qualified name of this class in the Handler input field of the AWS Lambda configuration page.

3.3. How Does AWS Know Which Cloud Function to Invoke?

As it turns out, even if we have more than one Spring Cloud Function in our application, AWS can invoke only one of them.

In the next section, we'll specify the cloud function name in an environment variable called FUNCTION_NAME on the AWS console.

4. Upload the Function to AWS and Test

Finally, let's build our jar with maven, and then upload it via the AWS Console UI.

4.1. Create a Lambda Function on AWS Console and Configure It

On the AWS Lambda console page, in the Function code section, we can select a Java 8 runtime and simply click Upload.

After that, we need to indicate in the Handler field the fully-qualified name of the class that implements SpringBootRequestHandler, or com.baeldung.spring.cloudfunction.MyStringHandlers in our case:

And then in Environment variables, we indicate which Spring function bean to invoke via the FUNCTION_NAME environment variable:

And having done that, it's time for us to test the Lambda function by creating a test event and supplying a sample string:

4.2. Testing the Function on AWS

Now, we Save our test, then click the Test button.

And, as expected, we get the same output as what we got when we tested the function locally:

4.3. Testing Another Function

Remember, we have one more function in our application: greeter. Let's make sure that works too.

We'll change the FUNCTION_NAME environment variable to greeter:

Click the Save button and finally, the Test button again:

5. Conclusion

In summary, though in its early stages, Spring Cloud Function is a powerful tool for decoupling the business logic from any specific runtime target.

Con esso, lo stesso codice può essere eseguito come endpoint Web, su una piattaforma cloud o come parte di un flusso. Astrae tutti i dettagli di trasporto e l'infrastruttura, consentendo allo sviluppatore di mantenere tutti gli strumenti e processi familiari e di concentrarsi saldamente sulla logica di business.

Come sempre, controlla il codice sorgente di questo tutorial su GitHub.