Sviluppo di funzioni locali

Le funzioni Cloud Run supportano diversi metodi di esecuzione delle funzioni al di fuori dell'ambiente di deployment di destinazione. Ciò è particolarmente utile per lo sviluppo iterativo e per le situazioni in cui vuoi testare la funzione prima del deployment.

La possibilità di eseguire le funzioni senza eseguirne il deployment può semplificare i test locali, la conformità alle limitazioni di località dei dati e i deployment multicloud:

  • Limitazioni della località dei dati: testa la funzione localmente senza accedere ai dati di produzione per evitare di violare le regole di località dei dati della tua organizzazione.

  • Deployment multicloud: i deployment di funzioni multicloud sono un pattern consolidato per ridurre il rischio di tempi di inattività in ambienti critici per l'affidabilità. Il deployment delle funzioni in ambienti diversi da Cloud Run Functions stesso riduce il rischio che la tua applicazione subisca tempi di inattività non pianificati.

Sviluppare funzioni localmente utilizzando Functions Framework

Puoi sviluppare e testare le funzioni localmente utilizzando Functions Framework. Lo sviluppo di una funzione in locale può aiutarti a testare il codice senza dover ricompilare il contenitore della funzione. In questo modo puoi risparmiare tempo e semplificare il test della funzione.

Cloud Run utilizza le librerie open source Functions Framework per racchiudere le funzioni di cui è stato eseguito il deployment in un'applicazione HTTP persistente.

Functions Framework può essere eseguito anche su qualsiasi altra piattaforma che supporti il linguaggio stesso, inclusi la macchina locale, i server on-premise e Compute Engine.

Installa le dipendenze

Nella directory della funzione, installa la libreria Functions Framework per il tuo linguaggio:

Node.js

npm install --save-dev @google-cloud/functions-framework

Python

pip3 install functions-framework

Vai

go install github.com/GoogleCloudPlatform/functions-framework-go/funcframework

Java

Maven

Se utilizzi Maven, aggiungi quanto segue al file pom.xml:

<dependency>
  <groupId>com.google.cloud.functions</groupId>
  <artifactId>functions-framework-api</artifactId>
  <version>1.1.0</version>
  <scope>provided</scope>
</dependency>

Gradle

Se utilizzi Gradle, aggiungi quanto segue al tuo file build.gradle:

dependencies {
  // Every function needs this dependency to get the Functions Framework API.
  compileOnly 'com.google.cloud.functions:functions-framework-api:1.1.0'

  // To run function locally using Functions Framework's local invoker
  invoker 'com.google.cloud.functions.invoker:java-function-invoker:1.3.1'
}

Per saperne di più, consulta la libreria del framework di Functions per Java.

C#

I seguenti comandi utilizzano i modelli .NET per creare una nuova base di codice della funzione .NET con la libreria.NET Functions Framework come dipendenza:

# HTTP functions
dotnet new gcf-http

# CloudEvent functions
dotnet new gcf-event

Ruby

In Ruby, Functions Framework deve essere aggiunto alle dipendenze della funzione per poter eseguire il deployment in Cloud Run:

bundle add functions_framework

PHP

composer require google/cloud-functions-framework

Configura il framework di Functions

Prima di eseguire una funzione utilizzando Functions Framework, devi prima specificare il tipo e il nome della funzione che vuoi eseguire. Questi attributi possono essere specificati come flag dell'interfaccia a riga di comando (CLI) o come variabili di ambiente.

Tipi di funzioni supportati

Functions Framework supporta entrambi i tipi di funzioni supportati da Cloud Run Functions. Tutti i runtime del linguaggio supportano i tipi di firma http e cloudevent.

Tipo di funzione Tipo di firma Descrizione Runtime supportati
Funzioni attivate da HTTP http Funzioni che ricevono e rispondono alle richieste HTTP. Tutti i runtime
Funzioni basate su eventi cloudevent Formato degli eventi standard di settore. Tutti i runtime

Specifica la funzione da eseguire

Prima di eseguire una funzione con Functions Framework, devi specificare quale funzione eseguire all'interno del codice. Per la maggior parte delle lingue, puoi farlo specificando il nome del metodo della funzione di destinazione come mostrato nelle tabelle seguenti. Tieni presente che esistono eccezioni a questa regola per i runtime Java e .NET.

Istruzioni per lingua

Consulta la tabella seguente per un elenco delle opzioni di configurazione supportate da ciascuna lingua.

Node.js

Argomento CLI Variabile di ambiente Descrizione
--port PORT La porta su cui rimanere in ascolto delle richieste. (Predefinito: 8080)
--target FUNCTION_TARGET Il nome della funzione exportda richiamare. (Predefinito: function)
--signature-type FUNCTION_SIGNATURE_TYPE Il tipo di firma utilizzato dalla funzione. Può essere http (valore predefinito) o cloudevent.

Python

Argomento CLI Variabile di ambiente Descrizione
--port PORT La porta su cui rimanere in ascolto delle richieste. (Predefinito: 8080)
--target FUNCTION_TARGET Il nome della funzione exportda richiamare. (Predefinito: function)
--signature-type FUNCTION_SIGNATURE_TYPE Il tipo di firma utilizzato dalla funzione. Può essere http (valore predefinito) o cloudevent.

Vai

Variabile di ambiente Descrizione
PORT La porta su cui rimanere in ascolto delle richieste. (Predefinito: 8080)

Java

Nome argomento Variabile di ambiente Descrizione
run.port PORT La porta su cui rimanere in ascolto delle richieste. (Predefinito: 8080)
run.functionTarget FUNCTION_TARGET Il nome della funzione exportda richiamare. (Predefinito: function)

C#

Argomento CLI Variabile di ambiente Descrizione
--port PORT La porta su cui rimanere in ascolto delle richieste. (Predefinito: 8080)
--target (o unico argomento) FUNCTION_TARGET Il nome della classe della funzione da richiamare. (Predefinito: function)

Ruby

Argomento CLI Variabile di ambiente Descrizione
--port PORT La porta su cui rimanere in ascolto delle richieste. (Predefinito: 8080)
--target FUNCTION_TARGET Il nome della funzione exportda richiamare. (Predefinito: function)

PHP

Variabile di ambiente Descrizione
FUNCTION_TARGET Il nome della funzione da richiamare. (Predefinito: function)
FUNCTION_SIGNATURE_TYPE Il tipo di firma utilizzato dalla funzione. Può essere http (valore predefinito) o cloudevent.

Segui queste istruzioni per configurare ed eseguire Functions Framework:

Node.js

Node.js Functions Framework ti consente di specificare il nome e il tipo di firma della funzione come argomenti della riga di comando o variabili di ambiente.

Puoi anche specificare questi valori nel file di build package.json aggiungendo uno script start con gli argomenti della CLI richiesti, come mostrato nell'esempio seguente.

"scripts": {
"start": "npx functions-framework --target=YOUR_FUNCTION_NAME [--signature-type=YOUR_SIGNATURE_TYPE]"
}

Lo stesso può essere fatto utilizzando le variabili di ambiente:

"scripts": {
"start": "FUNCTION_TARGET=YOUR_FUNCTION_NAME FUNCTION_SIGNATURE_TYPE=YOUR_SIGNATURE_TYPE npx functions-framework"
}

Sostituisci YOUR_FUNCTION_NAME con il nome del metodo della tua funzione e YOUR_SIGNATURE_TYPE (se applicabile) con il tipo di firma della tua funzione, come mostrato in Tipi di funzioni supportati.

Python

Python Functions Framework ti consente di specificare il nome e il tipo di firma della funzione come argomenti della riga di comando o variabili di ambiente. Gli argomenti della riga di comando devono essere specificati quando esegui il framework.

Vai

Go Functions Framework utilizza funcframework.RegisterHTTPFunctionContext per specificare il tipo di firma e il target della funzione.

Java

Java Functions Framework accetta i dati di configurazione da tre diverse origini, nel seguente ordine di priorità (dalla più specifica alla meno specifica):

  • Argomenti della riga di comando
  • Buildfiles
  • Variabili di ambiente

Argomenti della riga di comando

Maven

Puoi specificare la funzione che vuoi eseguire aggiungendo il seguente flag dell'interfaccia a riga di comando (CLI) ai comandi mvn:

-Drun.functionTarget=YOUR_FUNCTION_NAME

Puoi anche specificare la porta di destinazione aggiungendo il seguente flag CLI in modo simile:

-Drun.port=12345

Gradle

I flag della CLI di Gradle sono quasi identici a quelli di Maven. L'unica modifica apportata da Gradle consiste nello scambiare il -D iniziale in ogni flag con un -P, come mostrato nell'esempio seguente:

# Maven version

-Drun.functionTarget=...

# Gradle version

-Prun.functionTarget=...

Buildfiles

Puoi anche specificare la funzione che vuoi eseguire nel file di build del progetto. Sebbene Maven e Gradle abbiano flag CLI simili, le clausole dei file di build differiscono in modo significativo.

Maven

I file di build di Maven si chiamano pom.xml. Aggiungi la seguente clausola a questo file per specificare una funzione di destinazione:

<plugin>
  <groupId>com.google.cloud.functions</groupId>
  <artifactId>function-maven-plugin</artifactId>
  <version>0.11.0</version>
  <configuration>
    <functionTarget>functions.HelloWorld</functionTarget>
  </configuration>
</plugin>

Sostituisci <functionTarget> con il nome della classe della tua funzione. Ad esempio, una funzione nel pacchetto functions con nome della classe HelloCloudFunctions avrebbe un nome della classe functions.HelloCloudFunctions. Questo valore è relativo al file di build principale - pom.xml o build.gradle.

Gradle

I file di build Gradle sono denominati build.gradle. Aggiungi la seguente clausola a questo file per specificare una funzione di destinazione:

// Register a "runFunction" task to run the function locally
tasks.register("runFunction", JavaExec) {
  main = 'com.google.cloud.functions.invoker.runner.Invoker'
  classpath(configurations.invoker)
  inputs.files(configurations.runtimeClasspath, sourceSets.main.output)
  args(
    '--target', project.findProperty('run.functionTarget') ?: '',
    '--port', project.findProperty('run.port') ?: 8080
  )
  doFirst {
    args('--classpath', files(configurations.runtimeClasspath, sourceSets.main.output).asPath)
  }
}

C#

Se crei il progetto utilizzando dotnet new e uno dei modelli specificati in precedenza, .NET Functions Framework rileverà automaticamente la funzione.

Se il progetto contiene più funzioni, consulta la sezione Esecuzione del framework per informazioni su come eseguire una funzione specifica.

Ruby

Ruby Functions Framework ti consente di specificare il nome e il tipo di firma della funzione come argomenti della riga di comando o variabili di ambiente. Gli argomenti della riga di comando devono essere specificati quando esegui il framework.

PHP

Il framework di Functions per PHP ti consente di specificare variabili di ambiente come argomenti della riga di comando.

Puoi anche specificare questi valori nel file di build composer.json aggiungendo uno script start, come mostrato nell'esempio seguente.

"scripts": {
 "start": [
     "Composer\\Config::disableProcessTimeout",
     "FUNCTION_TARGET=YOUR_FUNCTION_NAME php -S localhost:${PORT:-8080} vendor/bin/router.php"
].
}

Sostituisci YOUR_FUNCTION_NAME con il nome della tua funzione e YOUR_SIGNATURE_TYPE (se applicabile; non è incluso nell'esempio mostrato qui).

Esegui la funzione

Utilizza questo comando per eseguire la funzione con Functions Framework. Per impostazione predefinita, la funzione sarà accessibile all'indirizzo localhost:8080, a meno che tu non specifichi esplicitamente un valore PORT.

Node.js

npm start

Python

Utilizzo degli argomenti della riga di comando:

functions-framework --target=YOUR_FUNCTION_NAME

Utilizzo delle variabili di ambiente:

FUNCTION_TARGET=YOUR_FUNCTION_NAME functions-framework

Sostituisci YOUR_FUNCTION_NAME con il nome del metodo della tua funzione.

Vai

Per prima cosa, crea un file cmd/main.go come descritto nel sito Functions Framework per Go.

cd cmd
go build
./cmd

Utilizzo delle variabili di ambiente:

cd cmd
go build
PORT=8080 ./cmd

Java

Maven

Utilizza il seguente comando per eseguire una funzione specificata in pom.xml:

mvn function:run

Utilizza il seguente comando per eseguire una funzione specificata in un argomento della riga di comando:

mvn function:run -Drun.functionTarget=YOUR_FUNCTION_NAME

Utilizza il comando seguente per eseguire una funzione specificata come variabile di ambiente:

FUNCTION_TARGET=YOUR_FUNCTION_NAME mvn function:run

Sostituisci YOUR_FUNCTION_NAME con il nome della classe della funzione.

Gradle

Utilizza il seguente comando per eseguire una funzione specificata in build.gradle:

./gradlew runFunction

Utilizza il seguente comando per eseguire una funzione specificata in un argomento della riga di comando:

./gradlew runFunction -Prun.functionTarget=YOUR_FUNCTION_NAME

Utilizza il comando seguente per eseguire una funzione specificata come variabile di ambiente:

FUNCTION_TARGET=YOUR_FUNCTION_NAME ./gradlew runFunction

Sostituisci YOUR_FUNCTION_NAME con il nome della classe della funzione.

C#

Utilizza il seguente comando per eseguire la funzione quando è presente esattamente una funzione nel progetto .NET corrente. Tieni presente che questa è la struttura predefinita per i progetti creati con i modelli.

dotnet run

Se il progetto .NET contiene più funzioni, utilizza il seguente comando per eseguire una funzione specifica. Sostituisci YOUR_FUNCTION_CLASSNAME con il nome della classe della tua funzione, incluso lo spazio dei nomi.

dotnet run YOUR_FUNCTION_CLASSNAME

Se vuoi eseguire più funzioni contemporaneamente, devi eseguire più istanze di Functions Framework. Per evitare conflitti tra le istanze del framework in esecuzione, ogni istanza deve utilizzare un valore PORT diverso. Il comando seguente mostra come eseguire una funzione con un valore PORT di 8080.

Utilizzo degli argomenti della riga di comando:

dotnet run --target YOUR_FUNCTION_CLASSNAME --port 8080

Utilizzo delle variabili di ambiente:

FUNCTION_TARGET=YOUR_FUNCTION_CLASSNAME PORT=8080 dotnet run

Ruby

Utilizzo degli argomenti della riga di comando:

bundle exec functions-framework-ruby --target YOUR_FUNCTION_NAME

Utilizzo delle variabili di ambiente:

FUNCTION_TARGET=YOUR_FUNCTION_NAME bundle exec functions-framework-ruby

Sostituisci YOUR_FUNCTION_NAME con il nome del metodo della tua funzione.

PHP

export FUNCTION_TARGET=YOUR_FUNCTION_NAME
php -S localhost:8080 vendor/bin/router.php

Sostituisci YOUR_FUNCTION_NAME con il nome della tua funzione.

Chiama la funzione in esecuzione in locale

Gli esercizi di questa sezione presuppongono che tu abbia configurato una funzione in esecuzione in locale su localhost utilizzando Functions Framework.

Puoi attivare le funzioni eseguite localmente inviando loro richieste HTTP instradate utilizzando un processo di pubblicazione locale.

Funzioni HTTP

Quando testi la funzione HTTP dall'ambiente di sviluppo, in genere ascolta le richieste su localhost:8080. Questa interfaccia è accessibile solo dalla macchina o dalla VM su cui viene eseguita la funzione; le richieste inviate da qualsiasi altro sistema non possono raggiungerla. Per questo motivo, devi inviare la richiesta HTTP dallo stesso sistema su cui viene eseguita la funzione. Negli esempi seguenti, se la tua funzione è in ascolto su una porta diversa da 8080, sostituisci 8080 nell'esempio con il numero di porta della tua funzione.

Test delle funzioni HTTP con Cloud Shell

Se utilizzi Cloud Shell per creare e testare la funzione, avviala localmente nella finestra del terminale Cloud Shell, quindi invia la richiesta di trigger HTTP da un browser o da un'istanza curl nel seguente modo:

Browser

Fai clic sull'icona Pulsante Anteprima web sulla barra degli strumenti di Cloud Shell e scegli porta 8080 o Cambia porta per selezionare una porta diversa. Si apre una finestra del browser sul sistema corretto e viene inviata una richiesta GET alla porta indicata.

Curl

Per controllare il formato della richiesta HTTP o per visualizzare la risposta non formattata, utilizza curl:

  1. Fai clic sull'icona + nella barra dei menu di Cloud Shell per aprire una nuova finestra del terminale nello stesso sistema in cui viene eseguita la funzione.
  2. All'interno di questa finestra, esegui il comando curl per attivare la funzione. Ad esempio:

    curl localhost:8080
    

Testare le funzioni HTTP sul server desktop

Se crei ed esegui la funzione sul tuo sistema desktop locale, prima avviala localmente, poi invia la richiesta di attivazione HTTP da un browser o da un'istanza curl nel seguente modo:

Browser

Apri una nuova finestra o scheda del browser e digita http://localhost:8080 nella barra degli indirizzi del browser. Si apre una finestra del browser su localhost:8080 sul server desktop per attivare la funzione.

Curl

Apri una nuova finestra del terminale sul desktop locale, quindi esegui il comando curl in quella finestra per attivare la funzione. Ad esempio:

 curl localhost:8080

Esegue il comando curl specificato per attivare la funzione e visualizza la risposta non formattata.

Funzioni basate su eventi

Puoi inviare eventi di esempio alle funzioni basate su eventi utilizzando curl. Le seguenti richieste curl mostrano come inviare eventi di esempio Pub/Sub e Cloud Storage a una funzione basata su eventi in esecuzione su localhost:8080.

Pub/Sub

curl localhost:8080 \
  -X POST \
  -H "Content-Type: application/json" \
  -H "ce-id: 123451234512345" \
  -H "ce-specversion: 1.0" \
  -H "ce-time: 2020-01-02T12:34:56.789Z" \
  -H "ce-type: google.cloud.pubsub.topic.v1.messagePublished" \
  -H "ce-source: //pubsub.googleapis.com/projects/MY-PROJECT/topics/MY-TOPIC" \
  -d '{
        "message": {
          "data": "d29ybGQ=",
          "attributes": {
             "attr1":"attr1-value"
          }
        },
        "subscription": "projects/MY-PROJECT/subscriptions/MY-SUB"
      }'
    

Cloud Storage

curl localhost:8080 \
  -X POST \
  -H "Content-Type: application/json" \
  -H "ce-id: 123451234512345" \
  -H "ce-specversion: 1.0" \
  -H "ce-time: 2020-01-02T12:34:56.789Z" \
  -H "ce-type: google.cloud.storage.object.v1.finalized" \
  -H "ce-source: //storage.googleapis.com/projects/_/buckets/MY-BUCKET-NAME" \
  -H "ce-subject: objects/MY_FILE.txt" \
  -d '{
        "bucket": "MY_BUCKET",
        "contentType": "text/plain",
        "kind": "storage#object",
        "md5Hash": "...",
        "metageneration": "1",
        "name": "MY_FILE.txt",
        "size": "352",
        "storageClass": "MULTI_REGIONAL",
        "timeCreated": "2020-04-23T07:38:57.230Z",
        "timeStorageClassUpdated": "2020-04-23T07:38:57.230Z",
        "updated": "2020-04-23T07:38:57.230Z"
      }'
    

Passaggi successivi