Entwicklung lokaler Funktionen

Cloud Run Functions unterstützt mehrere Methoden zum Ausführen von Funktionen außerhalb der Zielbereitstellungsumgebung. Dies ist besonders bei der iterativen Entwicklung und in Situationen nützlich, in denen Sie die Funktion vor der Bereitstellung testen möchten.

Die Möglichkeit, Funktionen ohne Bereitstellung auszuführen, kann lokale Tests, die Einhaltung von Datenlokalitätsbeschränkungen und Multi-Cloud-Bereitstellungen vereinfachen:

  • Datenlokalitätsbeschränkungen: Sie können Ihre Funktion lokal testen, ohne auf Produktionsdaten zuzugreifen, um Verstöße gegen die Datenlokalitätsregeln Ihrer Organisation zu vermeiden.

  • Multi-Cloud-Bereitstellungen: Multi-Cloud-Funktionsbereitstellungen sind eine gängige Methode, um das Ausfallrisiko in Umgebungen zu minimieren, in denen Zuverlässigkeit höchste Priorität hat. Die Bereitstellung von Funktionen in anderen Umgebungen als Cloud Run Functions verringert das Risiko von ungeplanten Ausfallzeiten Ihrer Anwendung.

Funktionen lokal mit Functions Framework entwickeln

Mit dem Functions Framework können Sie Funktionen lokal entwickeln und testen. Wenn Sie eine Funktion lokal entwickeln, können Sie Ihren Code testen, ohne den Funktionscontainer neu erstellen zu müssen. So können Sie Zeit sparen und die Funktion leichter testen.

Cloud Run verwendet die Open-Source-Bibliotheken des Functions Framework, um Ihre bereitgestellten Funktionen in einer nichtflüchtigen HTTP-Anwendung zu verpacken.

Das Functions Framework kann auch auf jeder anderen Plattform ausgeführt werden, die die Sprache selbst unterstützt, darunter lokale Computer, lokale Server und die Compute Engine.

Abhängigkeiten installieren

Installieren Sie im Verzeichnis der Funktion die Functions Framework-Bibliothek für Ihre Sprache:

Node.js

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

Python

pip3 install functions-framework

Go

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

Java

Maven

Wenn Sie Maven verwenden, fügen Sie der Datei pom.xml Folgendes hinzu:

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

Gradle

Wenn Sie Gradle verwenden, fügen Sie der Datei build.gradle Folgendes hinzu:

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'
}

Weitere Informationen finden Sie in der Java Functions Framework-Bibliothek.

C#

Die folgenden Befehle verwenden .NET-Vorlagen, um eine neue .NET-Funktions-Codebasis mit der .NET Functions Framework-Bibliothek als Abhängigkeit zu erstellen:

# HTTP functions
dotnet new gcf-http

# CloudEvent functions
dotnet new gcf-event

Ruby

In Ruby muss das Functions Framework den Funktionsabhängigkeiten hinzugefügt werden, um sie in Cloud Run bereitstellen zu können:

bundle add functions_framework

PHP

composer require google/cloud-functions-framework

Functions Framework konfigurieren

Bevor Sie eine Funktion mit dem Functions Framework ausführen, müssen Sie den Typ und den Namen der Funktion angeben, die Sie ausführen möchten. Diese Attribute können entweder als Flags in der Befehlszeile oder als Umgebungsvariablen angegeben werden.

Unterstützte Funktionstypen

Das Functions Framework unterstützt beide Arten von Funktionen, die von Cloud Run-Funktionen unterstützt werden. Alle Sprachlaufzeiten unterstützen sowohl die Signaturtypen http als auch cloudevent.

Funktionstyp Signaturtyp Beschreibung Unterstützende Laufzeiten
Durch HTTP ausgelöste Funktionen http Funktionen, die HTTP-Anfragen empfangen und beantworten. Alle Laufzeiten
CloudEvent-Funktionen cloudevent Branchenstandard-Ereignisformat. Alle Laufzeiten

Auszuführende Funktion angeben

Bevor Sie eine Funktion mit dem Functions Framework ausführen, müssen Sie festlegen, welche Funktion im Code ausgeführt werden soll. Für die meisten Sprachen können Sie dafür den Methodennamen der Zielfunktion angeben, wie in den folgenden Tabellen dargestellt. Für die Java- und .NET-Laufzeiten gibt es Ausnahmen von dieser Regel.

Anleitungen für die einzelnen Sprachen

Die folgende Tabelle enthält eine Liste der Konfigurationsoptionen, die von den einzelnen Sprachen unterstützt werden.

Node.js

Befehlszeilenargument Umgebungsvariable Beschreibung
--port PORT Der Port, auf dem Anfragen überwacht werden sollen. (Standardeinstellung: 8080)
--target FUNCTION_TARGET Der Name der exportierten Funktion, die aufgerufen werden soll. (Standard: function)
--signature-type FUNCTION_SIGNATURE_TYPE Der von der Funktion verwendete Signaturtyp. Kann http (Standard) oder cloudevent sein.

Python

Befehlszeilenargument Umgebungsvariable Beschreibung
--port PORT Der Port, auf dem Anfragen überwacht werden sollen. (Standardeinstellung: 8080)
--target FUNCTION_TARGET Der Name der exportierten Funktion, die aufgerufen werden soll. (Standard: function)
--signature-type FUNCTION_SIGNATURE_TYPE Der von der Funktion verwendete Signaturtyp. Kann http (Standard) oder cloudevent sein.

Go

Umgebungsvariable Beschreibung
PORT Der Port, auf dem Anfragen überwacht werden sollen. (Standardeinstellung: 8080)

Java

Name des Arguments Umgebungsvariable Beschreibung
run.port PORT Der Port, auf dem Anfragen überwacht werden sollen. (Standardeinstellung: 8080)
run.functionTarget FUNCTION_TARGET Der Name der exportierten Funktion, die aufgerufen werden soll. (Standard: function)

C#

Befehlszeilenargument Umgebungsvariable Beschreibung
--port PORT Der Port, auf dem Anfragen überwacht werden sollen. (Standardeinstellung: 8080)
--target (oder nur Argument) FUNCTION_TARGET Der classname der aufzurufenden Funktion. (Standard: function)

Ruby

Befehlszeilenargument Umgebungsvariable Beschreibung
--port PORT Der Port, auf dem Anfragen überwacht werden sollen. (Standardeinstellung: 8080)
--target FUNCTION_TARGET Der Name der exportierten Funktion, die aufgerufen werden soll. (Standard: function)

PHP

Umgebungsvariable Beschreibung
FUNCTION_TARGET Der Name der Funktion, die aufgerufen werden soll. (Standard: function)
FUNCTION_SIGNATURE_TYPE Der von der Funktion verwendete Signaturtyp. Kann http (Standard) oder cloudevent sein.

Folgen Sie dieser Anleitung, um das Functions Framework zu konfigurieren und auszuführen:

Node.js

Mit dem Node.js Functions Framework können Sie den Namen und den Signaturtyp der Funktion als Befehlszeilenargumente oder Umgebungsvariablen angeben.

Sie können diese Werte auch in der Build-Datei package.json angeben. Dazu fügen Sie ein start-Skript mit den erforderlichen Befehlszeilenargumenten hinzu, wie im folgenden Beispiel gezeigt.

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

Das Gleiche ist auch mit Umgebungsvariablen möglich:

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

Ersetzen Sie YOUR_FUNCTION_NAME durch den Methodennamen Ihrer Funktion und YOUR_SIGNATURE_TYPE (falls zutreffend) durch den Signaturtyp der Funktion, wie in den unterstützten Funktionstypen dargestellt.

Python

Mit dem Python Functions Framework können Sie den Namen und den Signaturtyp der Funktion als Befehlszeilenargumente oder Umgebungsvariablen angeben. Befehlszeilenargumente müssen beim Ausführen des Frameworks angegeben werden.

Go

Das Go Functions Framework verwendet funcframework.RegisterHTTPFunctionContext, um das Funktionsziel und den Signaturtyp anzugeben.

Java

Das Java Functions Framework akzeptiert Konfigurationsdaten aus drei verschiedenen Quellen in der folgenden Prioritätsreihenfolge (spezifischste zuerst):

  • Befehlszeilenargumente
  • Buildfiles
  • Umgebungsvariablen

Befehlszeilenargumente

Maven

Zum Angeben der auszuführenden Funktion fügen Sie den mvn-Befehlen das folgende Befehlszeilen-Flag (Befehlszeile) hinzu:

-Drun.functionTarget=YOUR_FUNCTION_NAME

Sie können den Zielport auch angeben, indem Sie das folgende Befehlszeilen-Flag auf ähnliche Weise hinzufügen:

-Drun.port=12345

Gradle

Die Befehlszeilen-Flags von Gradle sind fast identisch mit denen von Maven. Der einzige Unterschied zu Gradle besteht darin, dass das vorangestellte -D in jedem Flag durch ein -P ersetzt wird, wie im folgenden Beispiel gezeigt:

# Maven version

-Drun.functionTarget=...

# Gradle version

-Prun.functionTarget=...

Buildfiles

Sie können auch die Funktion angeben, die Sie in der Build-Datei Ihres Projekts ausführen möchten. Obwohl Maven und Gradle ähnliche Befehlszeilen-Flags haben, unterscheiden sich ihre Buildfile-Klauseln erheblich.

Maven

Maven-Build-Dateien haben den Namen pom.xml. Fügen Sie der Datei die folgende Klausel hinzu, um eine Zielfunktion anzugeben:

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

Ersetzen Sie <functionTarget> durch den Klassennamen der Funktion. Beispiel: Eine Funktion im Paket functions mit dem Klassennamen HelloCloudFunctions hätte den Klassennamen functions.HelloCloudFunctions. Dies bezieht sich auf die übergeordnete Build-Datei, entweder pom.xml oder build.gradle.

Gradle

Gradle-Build-Dateien haben den Namen build.gradle. Fügen Sie dieser Datei die folgende Klausel hinzu, um eine Zielfunktion anzugeben:

// 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#

Wenn Sie Ihr Projekt mit dotnet new und einer der oben genannten Vorlagen erstellen, erkennt das .NET Functions Framework die Funktion automatisch.

Wenn Ihr Projekt mehrere Funktionen enthält, lesen Sie den Abschnitt Framework ausführen, um Informationen zum Ausführen einer bestimmten Funktion zu erhalten.

Ruby

Mit dem Ruby Functions Framework können Sie den Namen und den Signaturtyp der Funktion als Befehlszeilenargumente oder Umgebungsvariablen angeben. Befehlszeilenargumente müssen beim Ausführen des Frameworks angegeben werden.

PHP

Im PHP Functions-Framework können Sie Umgebungsvariablen als Befehlszeilenargumente angeben.

Sie können diese Werte auch in der Build-Datei composer.json angeben, indem Sie ein start-Skript hinzufügen, wie im folgenden Beispiel gezeigt.

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

Ersetzen Sie YOUR_FUNCTION_NAME durch den Namen Ihrer Funktion und YOUR_SIGNATURE_TYPE (falls zutreffend; im Beispiel hier nicht enthalten).

Funktion ausführen

Verwenden Sie den folgenden Befehl, um die Funktion mit Functions Framework auszuführen. Standardmäßig ist die Funktion unter localhost:8080 zugänglich, sofern Sie nicht explizit einen PORT-Wert angeben.

Node.js

npm start

Python

Mit Befehlszeilenargumenten:

functions-framework --target=YOUR_FUNCTION_NAME

Mit Umgebungsvariablen:

FUNCTION_TARGET=YOUR_FUNCTION_NAME functions-framework

Ersetzen Sie YOUR_FUNCTION_NAME durch den Methodennamen der Funktion.

Go

Erstellen Sie zuerst eine Datei cmd/main.go, wie auf der Website Functions Framework für Go beschrieben.

cd cmd
go build
./cmd

Mit Umgebungsvariablen:

cd cmd
go build
PORT=8080 ./cmd

Java

Maven

Verwenden Sie den folgenden Befehl, um eine in pom.xml angegebene Funktion auszuführen:

mvn function:run

Verwenden Sie den folgenden Befehl, um eine in einem Befehlszeilenargument angegebene Funktion auszuführen:

mvn function:run -Drun.functionTarget=YOUR_FUNCTION_NAME

Verwenden Sie den folgenden Befehl, um eine als Umgebungsvariable angegebene Funktion auszuführen:

FUNCTION_TARGET=YOUR_FUNCTION_NAME mvn function:run

Ersetzen Sie YOUR_FUNCTION_NAME durch den Klassennamen der Funktion.

Gradle

Verwenden Sie den folgenden Befehl, um eine in build.gradle angegebene Funktion auszuführen:

./gradlew runFunction

Verwenden Sie den folgenden Befehl, um eine in einem Befehlszeilenargument angegebene Funktion auszuführen:

./gradlew runFunction -Prun.functionTarget=YOUR_FUNCTION_NAME

Verwenden Sie den folgenden Befehl, um eine als Umgebungsvariable angegebene Funktion auszuführen:

FUNCTION_TARGET=YOUR_FUNCTION_NAME ./gradlew runFunction

Ersetzen Sie YOUR_FUNCTION_NAME durch den Klassennamen der Funktion.

C#

Verwenden Sie den folgenden Befehl, um die Funktion auszuführen, wenn genau eine Funktion im aktuellen .NET-Projekt vorhanden ist. Dies ist die Standardstruktur für Projekte, die aus einer Vorlage erstellt wurden.

dotnet run

Wenn Ihr .NET-Projekt mehrere Funktionen enthält, verwenden Sie den folgenden Befehl, um eine bestimmte Funktion auszuführen. Ersetzen Sie YOUR_FUNCTION_CLASSNAME durch den Klassennamen der Funktion, einschließlich des Namespace.

dotnet run YOUR_FUNCTION_CLASSNAME

Wenn Sie mehrere Funktionen gleichzeitig ausführen möchten, müssen Sie mehrere Functions Framework-Instanzen ausführen. Zur Vermeidung von Konflikten zwischen ausgeführten Framework-Instanzen sollte jede Instanz einen anderen Wert für PORT verwenden. Der folgende Befehl zeigt, wie eine Funktion mit einem PORT-Wert von 8080 ausgeführt wird.

Mit Befehlszeilenargumenten:

dotnet run --target YOUR_FUNCTION_CLASSNAME --port 8080

Mit Umgebungsvariablen:

FUNCTION_TARGET=YOUR_FUNCTION_CLASSNAME PORT=8080 dotnet run

Ruby

Mit Befehlszeilenargumenten:

bundle exec functions-framework-ruby --target YOUR_FUNCTION_NAME

Mit Umgebungsvariablen:

FUNCTION_TARGET=YOUR_FUNCTION_NAME bundle exec functions-framework-ruby

Ersetzen Sie YOUR_FUNCTION_NAME durch den Methodennamen der Funktion.

PHP

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

Ersetzen Sie YOUR_FUNCTION_NAME durch den Namen der Funktion.

Lokal ausgeführte Funktion aufrufen

Bei den Übungen in diesem Abschnitt wird davon ausgegangen, dass Sie mithilfe des Functions Frameworks eine lokal ausgeführte Funktion in localhost eingerichtet haben.

Sie können lokal ausgeführte Funktionen auslösen, indem Sie HTTP-Anfragen senden, die über einen lokalen Bereitstellungsprozess weitergeleitet werden.

HTTP-Funktionen

Wenn Sie Ihre HTTP-Funktion in Ihrer Entwicklungsumgebung testen, wartet sie normalerweise auf Anfragen unter localhost:8080. Diese Schnittstelle ist nur von dem Computer oder der VM aus zugänglich, auf dem bzw. der Ihre Funktion ausgeführt wird. Anfragen, die von einem anderen System gesendet werden, können sie nicht erreichen. Aus diesem Grund müssen Sie die HTTP-Anfrage von demselben System aus senden, auf dem Ihre Funktion ausgeführt wird. Wenn Ihre Funktion in den folgenden Beispielen einen anderen Port als 8080 überwacht, ersetzen Sie 8080 im Beispiel durch die Portnummer für Ihre Funktion.

HTTP-Funktionen mit Cloud Shell testen

Wenn Sie Cloud Shell zum Erstellen und Testen Ihrer Funktion verwenden, starten Sie die Funktion lokal im Cloud Shell-Terminalfenster und senden Sie dann die HTTP-Triggeranfrage über einen Browser oder eine curl-Instanz wie unten beschrieben:

Browser

Klicken Sie in der Cloud Shell-Symbolleiste auf das Symbol Schaltfläche für Webvorschau und wählen Sie Port 8080 oder Port ändern aus, um einen anderen Port auszuwählen. Dadurch wird ein Browserfenster auf dem richtigen System geöffnet und ein GET-Request an den angegebenen Port gesendet.

Curl

Wenn Sie das Format Ihrer HTTP-Anfrage steuern oder die unformatierte Antwort sehen möchten, verwenden Sie curl:

  1. Klicken Sie in der Cloud Shell-Menüleiste auf das Symbol +, um ein neues Terminalfenster auf demselben System zu öffnen, auf dem Ihre Funktion ausgeführt wird.
  2. Führen Sie in diesem Fenster den Befehl curl aus, um die Funktion auszulösen. Beispiel:

    curl localhost:8080
    

HTTP-Funktionen auf dem Desktopserver testen

Wenn Sie Ihre Funktion auf Ihrem lokalen Desktopsystem erstellen und ausführen, starten Sie sie zuerst lokal und senden Sie dann die HTTP-Triggeranfrage über einen Browser oder eine curl-Instanz wie unten beschrieben:

Browser

Öffnen Sie ein neues Browserfenster oder einen neuen Tab und geben Sie http://localhost:8080 in die Adressleiste des Browsers ein. Dadurch wird ein Browserfenster mit localhost:8080 auf Ihrem Desktopserver geöffnet, um Ihre Funktion auszulösen.

Curl

Öffnen Sie auf Ihrem lokalen Computer ein neues Terminalfenster und führen Sie dann den Befehl curl in diesem Fenster aus, um die Funktion auszulösen. Beispiel:

 curl localhost:8080

Dadurch wird der angegebene curl-Befehl ausgeführt, um die Funktion auszulösen, und die unformatierte Antwort wird angezeigt.

CloudEvent-Funktionen

Mit curl können Sie Beispielereignisse an CloudEvent-Funktionen senden. Die folgenden curl-Anfragen zeigen, wie Beispiele für Cloud Pub/Sub- und Cloud Storage-Ereignisse an eine CloudEvent-Funktion gesendet werden, die unter localhost:8080 ausgeführt wird.

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"
      }'