Google Cloud Functions in C#

1. Introduzione

Google Cloud Run Functions è una piattaforma di serverless computing basata sugli eventi. Cloud Run Functions ti consente di scrivere il codice senza preoccuparti del provisioning delle risorse o dello scaling per gestire i requisiti in evoluzione.

Esistono due tipi di funzioni Cloud Run:

  • Le funzioni HTTP rispondono alle richieste HTTP.
  • Le funzioni basate su eventi vengono attivate da eventi, ad esempio la pubblicazione di un messaggio in Cloud Pub/Sub o il caricamento di un file in Cloud Storage.

efb3268e3b74ed4f.png

Questo codelab ti guiderà nella creazione delle tue funzioni Cloud Run in C#. Più nello specifico, eseguirai il deployment di funzioni C# che rispondono a HTTP e CloudEvents da varie origini Google Cloud.

Obiettivi didattici

  • Framework di Functions per .NET.
  • Come scrivere una funzione HTTP.
  • Come scrivere una funzione attivata da eventi che risponde agli eventi Cloud Storage.
  • Come scrivere una funzione attivata da eventi che risponde agli eventi Cloud Pub/Sub.
  • Come scrivere una funzione attivata da eventi che risponde a qualsiasi tipo di evento.

2. Configurazione e requisiti

Configurazione dell'ambiente autonomo

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Il nome del progetto è il nome visualizzato per i partecipanti a questo progetto. È una stringa di caratteri non utilizzata dalle API di Google. Puoi aggiornarlo in qualsiasi momento.
  • L'ID progetto deve essere univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca, di solito non ti interessa di cosa si tratta. Nella maggior parte dei codelab, devi fare riferimento all'ID progetto (in genere è identificato come PROJECT_ID). Se non ti piace l'ID generato, puoi generarne un altro casuale. In alternativa, puoi provare a crearne uno e vedere se è disponibile. Non può essere modificato dopo questo passaggio e rimarrà per tutta la durata del progetto.
  • Per tua informazione, esiste un terzo valore, un numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, devi abilitare la fatturazione in Cloud Console per utilizzare le risorse/API Cloud. L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Per arrestare le risorse in modo da non incorrere in costi di fatturazione al termine di questo tutorial, puoi eliminare le risorse che hai creato o l'intero progetto. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.

Avvia Cloud Shell

Sebbene Google Cloud possa essere gestito da remoto dal tuo laptop, in questo codelab utilizzerai Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

Nella console Google Cloud, fai clic sull'icona di Cloud Shell nella barra degli strumenti in alto a destra:

55efc1aaa7a4d3ad.png

Bastano pochi istanti per eseguire il provisioning e connettersi all'ambiente. Al termine, dovresti vedere un risultato simile a questo:

7ffe5cbb04455448.png

Questa macchina virtuale è caricata con tutti gli strumenti per sviluppatori di cui avrai bisogno. Offre una home directory permanente da 5 GB e viene eseguita su Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Tutto il lavoro in questo codelab può essere svolto all'interno di un browser. Non devi installare nulla.

3. Prima di iniziare

In Cloud Shell, esegui questo comando per abilitare i servizi richiesti:

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  eventarc.googleapis.com \
  run.googleapis.com

Poi, imposta la regione.

REGION=<YOUR_REGION>

Per questo codelab, creerai un service account con le autorizzazioni Eventarc richieste e il ruolo Invoker di Cloud Run per ricevere un evento da Cloud Storage e richiamare la funzione Cloud Run.

Innanzitutto, crea il service account.

PROJECT_ID=$(gcloud config get-value core/project)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

SERVICE_ACCOUNT="cloud-run-functions"
SERVICE_ACCOUNT_ADDRESS=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com

gcloud iam service-accounts create $SERVICE_ACCOUNT \
  --display-name="Cloud Run functions Eventarc service account"

Successivamente, concedi il ruolo Destinatario di eventi Eventarc (roles/eventarc.eventReceiver) al progetto al service account associato al trigger Eventarc in modo che il trigger possa ricevere eventi dai provider di eventi.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/eventarc.eventReceiver

Poi, concedi al service account il ruolo Invoker di Cloud Run in modo che possa richiamare la funzione.

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
  --role=roles/run.invoker

4. Framework di Functions per .NET

Functions Framework per .NET è un framework FaaS (Function as a Service) open source per scrivere funzioni .NET portabili, creato dal team di Google Cloud Functions.

Il framework di Functions ti consente di scrivere funzioni leggere che vengono eseguite in molti ambienti diversi, tra cui:

  • Google Cloud Run Functions
  • La tua macchina di sviluppo locale
  • Cloud Run e Cloud Run su GKE
  • Ambienti basati su Knative

In questo codelab, utilizzerai Functions Framework per .NET e i relativi modelli per creare ed eseguire il deployment di Cloud Functions in C#.

In Cloud Shell, esegui questo comando per installare i modelli di Cloud Functions per dotnet:

dotnet new install Google.Cloud.Functions.Templates

Vengono installati tre modelli per dotnet. Ogni modello è disponibile in C#, F# e VB (ma in questo lab utilizzerai solo C#). Per verificare che i modelli siano installati, esegui il comando:

dotnet new list

Templates                                                 Short Name            
-----------------------------------------------------------------------
Google Cloud Functions CloudEvent Function                gcf-event
Google Cloud Functions CloudEvent Function (Untyped)      gcf-untyped-event
Google Cloud Functions HttpFunction                       gcf-http

5. Funzione HTTP

Creerai ed eseguirai il deployment di una funzione HTTP che risponde alle richieste HTTP.

Crea una funzione HTTP utilizzando il modello gcf-http:

mkdir HelloHttp
cd HelloHttp
dotnet new gcf-http

Vengono creati un progetto e un file Function.cs che risponde alle richieste HTTP.

Modifica il framework di destinazione impostandolo su net8.0 nel file .csproj:

<TargetFramework>net8.0</TargetFramework>

Per eseguire il deployment di una funzione Cloud Run direttamente su Cloud Run, esegui questo comando:

gcloud beta run deploy hello-http-function \
    --source . \
    --function HelloHttp.Function \
    --base-image dotnet8 \
    --region $REGION \
    --allow-unauthenticated

Se preferisci eseguire il deployment come Cloud Functions (2nd gen), utilizza il seguente comando:

gcloud functions deploy hello-http-function \
    --allow-unauthenticated \
    --entry-point HelloHttp.Function \
    --gen2 \
    --region $REGION \
    --runtime dotnet8 \
    --trigger-http

Una volta eseguito il deployment della funzione, puoi richiamarla utilizzando il seguente comando curl:

SERVICE_URL=$(gcloud run services describe hello-http-function --platform managed --region $REGION --format 'value(status.url)')

curl $SERVICE_URL

6. Funzione CloudEvent - GCS

Creerai e implementerai una funzione CloudEvent che risponde agli eventi Google Cloud Storage (GCS).

Innanzitutto, crea un bucket Cloud Storage. Questo è il bucket da cui ascolterai gli eventi in un secondo momento:

BUCKET_NAME="cloud-functions-bucket-${PROJECT_ID}"
gsutil mb -l us-central1 gs://${BUCKET_NAME}

Crea una funzione CloudEvent utilizzando il modello gcf-event:

cd ..
mkdir HelloGcs
cd HelloGcs
dotnet new gcf-event

Vengono creati un progetto e un file Function.cs che risponde alle richieste CloudEvent. Analizza anche i dati di CloudEvent in StorageObjectData.

Modifica il framework di destinazione impostandolo su net8.0 nel file .csproj:

<TargetFramework>net8.0</TargetFramework>

Per eseguire il deployment di una funzione Cloud Run direttamente su Cloud Run, devi prima eseguire il deployment della funzione e poi creare un trigger.

gcloud beta run deploy hello-gcs-function \
      --source . \
      --function HelloGcs.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated

Ora crea il trigger per la funzione Cloud Run

BUCKET_REGION=$REGION

gcloud eventarc triggers create hello-gcs-function-trigger \
     --location=$REGION \
     --destination-run-service=hello-gcs-function \
    --destination-run-region=$BUCKET_REGION \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=$BUCKET_NAME" \
     --service-account=$SERVICE_ACCOUNT_ADDRESS

Se preferisci eseguire il deployment come Cloud Functions (2nd gen), puoi utilizzare il seguente comando per eseguire il deployment della funzione utilizzando i flag trigger-event e trigger-resource:

gcloud functions deploy hello-gcs-function \
    --allow-unauthenticated \
    --entry-point HelloGcs.Function \
    --gen2 \
    --region $REGION \
    --runtime dotnet8 \
    --trigger-event google.storage.object.finalize \
    --trigger-resource ${BUCKET_NAME} \
    --service-account=$SERVICE_ACCOUNT_ADDRESS

Dopo un paio di minuti, la funzione dovrebbe essere visibile in Cloud Console:

c28654d74bb31420.png

Attiva la funzione caricando un file nel bucket di archiviazione:

echo "Hello from Storage" > random.txt
gsutil cp random.txt gs://${BUCKET_NAME}

Verifica che la funzione sia stata attivata leggendo i log:

Per una funzione Cloud Run, puoi eseguire questo comando:

gcloud logging read "resource.labels.service_name=hello-gcs-function AND textPayload: Name" --format=json

Per una funzione di 2ª gen., puoi eseguire questo comando:

gcloud functions logs read hello-gcs-function \
    --gen2 \
    --region us-central1

7. Funzione CloudEvent - Pub/Sub

Creerai ed eseguirai il deployment di una funzione CloudEvent che risponde agli eventi Cloud Pub/Sub.

Innanzitutto, crea un argomento Cloud Pub/Sub che genererà eventi:

TOPIC_NAME=cloud-functions-topic
gcloud pubsub topics create ${TOPIC_NAME}

Crea una funzione CloudEvent utilizzando il modello gcf-event:

cd ..
mkdir HelloPubSub
cd HelloPubSub
dotnet new gcf-event

Vengono creati un progetto e un file Function.cs che risponde alle richieste CloudEvent. Inoltre, analizza i dati di CloudEvent in StorageObjectData per impostazione predefinita.

Modifica il framework di destinazione impostandolo su net8.0 nel file .csproj:

<TargetFramework>net8.0</TargetFramework>

Modifica StorageObjectData in MessagePublishedData per analizzare i messaggi Pub/Sub. Modifica Google.Events.Protobuf.Cloud.Storage.V1 in Google.Events.Protobuf.Cloud.PubSub.V1.

Alla fine, la funzione dovrebbe avere il seguente aspetto:

using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.PubSub.V1;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace HelloPubSub;

public class Function : ICloudEventFunction<MessagePublishedData>
{
    public Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data, CancellationToken cancellationToken)
    {
        var nameFromMessage = data.Message?.TextData;
        var name = string.IsNullOrEmpty(nameFromMessage) ? "world" : nameFromMessage;
        Console.WriteLine($"Hello {name}");
        return Task.CompletedTask;
    }
}

Per eseguire il deployment di una funzione Cloud Run direttamente su Cloud Run, devi prima eseguire il deployment della funzione e poi creare un trigger.

gcloud beta run deploy hello-pubsub-function \
      --source . \
      --function HelloPubSub.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated \
      --service-account=$SERVICE_ACCOUNT_ADDRESS

Ora crea il trigger per la funzione Cloud Run

gcloud eventarc triggers create my-pubsub-trigger \
    --location=$REGION \
    --service-account=$SERVICE_ACCOUNT_ADDRESS \
    --destination-run-service=hello-pubsub-function \
    --destination-run-region=$REGION \
    --destination-run-path="/" \
    --event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
    --transport-topic=projects/$PROJECT_ID/topics/$TOPIC_NAME

Se preferisci eseguire il deployment come Cloud Functions (2nd gen), puoi utilizzare il seguente comando per eseguire il deployment della funzione utilizzando il flag trigger-topic:

gcloud functions deploy hello-pubsub-function \
    --allow-unauthenticated \
    --entry-point HelloPubSub.Function \
    --gen2 \
    --region us-central1 \
    --runtime dotnet8 \
    --trigger-topic ${TOPIC_NAME}

Dopo un paio di minuti, la funzione dovrebbe essere visibile in Cloud Console:

3443808da7caf3bc.png

Attiva la funzione pubblicando un messaggio nell'argomento:

gcloud pubsub topics publish ${TOPIC_NAME} --message="World"

Verifica che la funzione sia stata attivata leggendo i log.

Per una funzione Cloud Run, puoi eseguire questo comando:

gcloud logging read "resource.labels.service_name=hello-pubsub-function AND textPayload: World" --format=json

Per una funzione di 2ª gen., puoi eseguire questo comando:

gcloud functions logs read hello-pubsub-function \
    --gen2 \
    --region us-central1

8. Funzione CloudEvent - Senza tipo

Se stai sperimentando CloudEvents e non hai ancora un modello di dati del payload a cui vuoi fare riferimento o vuoi che la tua funzione sia in grado di gestire qualsiasi CloudEvent, puoi utilizzare una funzione CloudEvent senza tipo.

Crea una funzione CloudEvent utilizzando il modello gcf-untyped-event:

cd ..
mkdir HelloUntyped
cd HelloUntyped
dotnet new gcf-untyped-event

In questo modo viene creato un progetto e un file Function.cs che risponde alle richieste CloudEvent senza alcun tentativo di analizzare i dati di CloudEvent.

Modifica il framework di destinazione impostandolo su net8.0 nel file .csproj:

<TargetFramework>net8.0</TargetFramework>

Per eseguire il deployment di una funzione Cloud Run direttamente su Cloud Run, devi prima eseguire il deployment della funzione e poi creare un trigger.

gcloud beta run deploy hello-untyped-function \
      --source . \
      --function HelloUntyped.Function \
      --region $REGION \
      --base-image dotnet8 \
      --no-allow-unauthenticated

Ora crea il trigger per la funzione Cloud Run

BUCKET_REGION=$REGION

gcloud eventarc triggers create hello-untyped-function-trigger \
     --location=$REGION \
     --destination-run-service=hello-untyped-function \
    --destination-run-region=$BUCKET_REGION \
     --event-filters="type=google.cloud.storage.object.v1.finalized" \
     --event-filters="bucket=$BUCKET_NAME" \
     --service-account=$SERVICE_ACCOUNT_ADDRESS

Se preferisci eseguire il deployment come Cloud Functions (2nd gen), puoi utilizzare il seguente comando per eseguire il deployment della funzione utilizzando i flag trigger-event e trigger-resource:

gcloud functions deploy hello-untyped-function \
    --allow-unauthenticated \
    --entry-point HelloUntyped.Function \
    --gen2 \
    --region us-central1 \
    --runtime dotnet8 \
    --trigger-event google.storage.object.finalize \
    --trigger-resource ${BUCKET_NAME}

La funzione viene attivata quando un file viene caricato in un bucket di archiviazione.

Dopo un paio di minuti, la funzione dovrebbe essere visibile in Cloud Console:

afe56530826787c6.png

Attiva la funzione caricando un file nel bucket di archiviazione:

echo "Hello from Storage" > random.txt
gsutil cp random.txt gs://${BUCKET_NAME}

Verifica che la funzione sia stata attivata leggendo i log.

Per una funzione Cloud Run, puoi eseguire questo comando:

gcloud logging read "resource.labels.service_name=hello-gcs-function AND textPayload: Name" --format=json

Per una funzione di 2ª gen., puoi eseguire questo comando:

gcloud functions logs read hello-untyped-function \
    --gen2 \
    --region us-central1

9. Complimenti!

Congratulazioni per aver completato il codelab.

Argomenti trattati

  • Framework di Functions per .NET.
  • Come scrivere una funzione Cloud Functions HTTP.
  • Come scrivere una funzione CloudEvent che risponde agli eventi Cloud Storage.
  • Come scrivere una funzione CloudEvent che risponde agli eventi Cloud Pub/Sub.
  • Come scrivere una funzione CloudEvent che risponde a qualsiasi tipo di evento.