Ausführungsumgebung von Cloud Functions-Funktionen

Cloud Run Functions-Funktionen werden in einer vollständig verwalteten, serverlosen Umgebung ausgeführt, in der Google sich um die Verwaltung der Infrastruktur, Betriebssysteme und Laufzeitumgebungen kümmert. Jede Cloud Functions-Funktion wird in ihrem eigenen isolierten, sicheren Ausführungskontext bereitgestellt und automatisch skaliert. Ihr Lebenszyklus ist von dem anderer Funktionen unabhängig.

Laufzeiten

Cloud Run Functions unterstützt mehrere Sprachlaufzeiten. Jede enthält eine Standardreihe von Systempaketen sowie die Tools und Bibliotheken, die für diese Sprache benötigt werden. Sie benötigen den Laufzeit-ID-Wert, wenn Sie Funktionen über die Befehlszeile oder über Terraform bereitstellen.

Sicherheits- und Wartungsupdates werden für alle Ausführungsumgebungen der 1. und 2. Generation bereitgestellt. Diese Updates werden automatisch oder manuell angewendet, je nach Umgebung und Ihrer Konfiguration. Weitere Informationen zu Updates der Ausführungsumgebung finden Sie unter Cloud Run Functions-Funktionen schützen.

Node.js

Laufzeit Generierung Umgebung Laufzeit-ID Laufzeit-Image
Node.js 22 2. Generation Ubuntu 22.04 nodejs22 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22
Node.js 20 1. Generation, 2. Generation Ubuntu 22.04 nodejs20 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs20
Node.js 18 1. Generation, 2. Generation Ubuntu 22.04 nodejs18 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs18
Node.js 16 1. Generation, 2. Generation Ubuntu 18.04 nodejs16 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs16
Node.js 14 1. Generation, 2. Generation Ubuntu 18.04 nodejs14 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs14
Node.js 12 1. Generation, 2. Generation Ubuntu 18.04 nodejs12 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs12
Node.js 10 1. Generation, 2. Generation Ubuntu 18.04 nodejs10 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs10
Node.js 8 1. Generation, 2. Generation Ubuntu 18.04 nodejs8 Außer Betrieb genommen
Node.js 6 1. Generation, 2. Generation Ubuntu 18.04 nodejs6 Außer Betrieb genommen

Python

Laufzeit Generierung Umgebung Laufzeit-ID Laufzeit-Image
Python 3.12 1. Generation, 2. Generation Ubuntu 22.04 python312 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python312
Python 3.11 1. Generation, 2. Generation Ubuntu 22.04 python311 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python311
Python 3.10 1. Generation, 2. Generation Ubuntu 22.04 python310 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python310
Python 3.9 1. Generation, 2. Generation Ubuntu 18.04 python39 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python39
Python 3.8 1. Generation, 2. Generation Ubuntu 18.04 python38 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python38
Python 3.7 1. Generation Ubuntu 18.04 python37 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python37

Go

Laufzeit Generierung Umgebung Laufzeit-ID Laufzeit-Image
Go 1.23
(nur Vorabversion)
2. Generation Ubuntu 22.04 go123 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go123
Go 1.22 2. Generation Ubuntu 22.04 go122 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go122
Go 1.21 1. Generation, 2. Generation Ubuntu 22.04 go121 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go121
Go 1.20 1. Generation, 2. Generation Ubuntu 22.04 go120 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go120
Go 1.19 1. Generation, 2. Generation Ubuntu 22.04 go119 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go119
Go 1.18 1. Generation, 2. Generation Ubuntu 22.04 go118 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go118
Go 1.16 1. Generation, 2. Generation Ubuntu 18.04 go116 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go116
Go 1.13 1. Generation, 2. Generation Ubuntu 18.04 go113 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go113
Go 1.11 1. Generation, 2. Generation Ubuntu 18.04 go111 Außer Betrieb genommen

Java

Laufzeit Generierung Umgebung Laufzeit-ID Laufzeit-Image
Java 21 2. Generation Ubuntu 22.04 java21 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java21
Java 17 1. Generation, 2. Generation Ubuntu 22.04 java17 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java17
Java 11 1. Generation, 2. Generation Ubuntu 18.04 java11 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/java11

Ruby

Laufzeit Generierung Umgebung Laufzeit-ID Laufzeit-Image
Ruby 3.3 1. Generation, 2. Generation Ubuntu 22.04 ruby33 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.2 1. Generation, 2. Generation Ubuntu 22.04 ruby32 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.0 1. Generation, 2. Generation Ubuntu 18.04 ruby30 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby30
Ruby 2.7 1. Generation, 2. Generation Ubuntu 18.04 ruby27 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby27
Ruby 2.6 1. Generation, 2. Generation Ubuntu 18.04 ruby26 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby26

PHP

Laufzeit Umgebung Generierung Laufzeit-ID Laufzeit-Image
PHP 8.3 2. Generation Ubuntu 22.04 php83 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php83
PHP 8.2 1. Generation, 2. Generation Ubuntu 22.04 php82 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php82
PHP 8.1 1. Generation, 2. Generation Ubuntu 18.04 php81 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php81
PHP 7.4 1. Generation, 2. Generation Ubuntu 18.04 php74 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php74

.NET Core

Laufzeit Generierung Umgebung Laufzeit-ID Laufzeit-Image
.NET Core 8 2. Generation Ubuntu 22.04 dotnet8 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet8
.NET Core 6 1. Generation, 2. Generation Ubuntu 22.04 dotnet6 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet6
.NET Core 3 1. Generation, 2. Generation Ubuntu 18.04 dotnet3 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/dotnet3

Verhalten von Autoscaling

Cloud Run Functions ist eine serverlose Umgebung. Sie müssen sich bei der Codeausführung also nicht um die darunterliegende Infrastruktur wie Server oder virtuelle Maschinen kümmern. Nach der Bereitstellung werden die Funktionen automatisch verwaltet und skaliert.

Cloud Run Functions verarbeitet eingehende Anfragen, indem diese den Instanzen Ihrer Funktion zugewiesen werden. Abhängig von der Anzahl der Anfragen sowie der Anzahl der vorhandenen Funktionsinstanzen kann Cloud Run Functions eine Anfrage einer vorhandenen Instanz zuweisen oder eine neue erstellen.

Wenn das Volumen der eingehenden Anfragen die Anzahl der vorhandenen Instanzen überschreitet, kann Cloud Run Functions mehrere neue Instanzen zur Verarbeitung von Anfragen starten. Dieses automatische Skalierungsverhalten ermöglicht es Cloud Run Functions, viele Anfragen parallel zu verarbeiten, wobei jede eine andere Instanz Ihrer Funktion verwendet.

In einigen Fällen kann eine unbegrenzte Skalierung unerwünscht sein. Zur Behebung dieses Problems können Sie in Cloud Run Functions eine maximale Anzahl von Instanzen konfigurieren, die zu einer bestimmten Zeit für eine bestimmte Funktion koexistieren können.

Zustandslosigkeit

Wenn Sie die automatische Verwaltung und Skalierung der Funktionen aktivieren möchten, müssen sie zustandslos sein. Ein Funktionsaufruf darf nicht auf dem Speicherzustand basieren, der durch einen vorherigen Aufruf festgelegt wurde. Aufrufe können von verschiedenen Funktionsinstanzen verarbeitet werden, die nicht die gleichen globalen Variablen, Speicher, Dateisysteme oder andere Zustände haben.

Wenn Sie den Status für Funktionsaufrufe freigeben müssen, sollte die Funktion einen Dienst wie Memorystore, Datastore, Firestore oder Cloud Storage verwenden, um Daten zu speichern. Weitere Informationen zu Datenbank- und Speicheroptionen von Google Cloud finden Sie unter Google Cloud-Datenbanken und Google Cloud-Speicherprodukte.

Gleichzeitigkeit

Cloud Run-Funktionen (2. Generation)

Cloud Run Functions (2. Generation) unterstützt die Verarbeitung mehrerer gleichzeitiger Anfragen auf einer einzelnen Funktionsinstanz. Dies kann hilfreich sein, um Kaltstarts zu verhindern, da eine bereits vorbereitete Instanz mehrere Anfragen gleichzeitig verarbeiten kann, wodurch die Gesamtlatenz verringert wird. Weitere Informationen finden Sie unter Nebenläufigkeit.

Cloud Run Functions (1. Generation)

In Cloud Run Functions (1. Generation) wird von jeder Instanz einer Funktion jeweils nur eine gleichzeitige Anfrage verarbeitet. Das bedeutet, dass keine zweite Anfrage an dieselbe Instanz weitergeleitet werden kann, während Ihr Code eine Anfrage verarbeitet. Die ursprüngliche Anfrage kann also die gesamte von Ihnen zugewiesene Anzahl von Ressourcen (Arbeitsspeicher und CPU) nutzen.

Da gleichzeitige Anfragen in Cloud Run Functions (1. Generation) von verschiedenen Funktionsinstanzen verarbeitet werden, teilen diese keine Variablen oder lokalen Arbeitsspeicher. Weitere Informationen finden Sie unter Zustandslosigkeit und Lebensdauer von Funktionsinstanzen.

Kaltstarts

Eine neue Funktionsinstanz wird in zwei Fällen gestartet:

  • Wenn Sie die Funktion bereitstellen

  • Wenn die Funktion als Reaktion auf eine gestiegene Arbeitslast oder als Ersatz für eine andere Instanz automatisch erstellt wird.

Beim Starten einer neuen Funktionsinstanz werden die Laufzeit und der Code geladen. Anfragen, die den Start einer Funktionsinstanz (Kaltstart) enthalten, können langsamer sein als Anfragen, die an vorhandene Funktionsinstanzen weitergeleitet werden. Wenn Ihre Funktion eine konstante Workload verarbeitet, ist die Anzahl der Kaltstarts normalerweise vernachlässigbar, es sei denn, sie stürzt häufig ab und die Funktionsumgebung muss neu gestartet werden.

Wenn Ihr Funktionscode eine nicht abgefangene Ausnahme auslöst oder den aktuellen Prozess zum Abstürzen bringt, kann die Funktionsinstanz neu gestartet werden. Das kann zu Kaltstarts und damit einer höheren Latenz führen. Daher empfehlen wir, Ausnahmen abzufangen und andernfalls die Beendigung des aktuellen Prozesses zu vermeiden. Unter Fehler melden erfahren Sie, wie Sie Fehler in Cloud Run Functions verarbeiten und melden.

Wenn Ihre Funktion latenzempfindlich ist, sollten Sie eine Mindestzahl von Instanzen festlegen, um Kaltstarts zu vermeiden.

Lebensdauer einer Funktionsinstanz

Funktionsinstanzen sind in der Regel ausfallsicher und werden von nachfolgenden Funktionsaufrufen wiederverwendet, es sei denn, die Anzahl der Instanzen wird verkleinert, da der laufende Traffic fehlt oder die Funktion abstürzt. Das bedeutet, wenn eine Funktionsausführung endet, kann dieselbe Funktionsinstanz einen weiteren Funktionsaufruf verarbeiten.

Funktionsbereich oder globaler Bereich

Beim Aufrufen einer einzelnen Funktion wird nur der als Einstiegspunkt deklarierte Funktionsteil ausgeführt. Der globale Geltungsbereich des Funktionsquellcodes wird nur bei Kaltstarts und nicht bei Instanzen ausgeführt, die bereits initialisiert wurden.

Node.js

const functions = require('@google-cloud/functions-framework');

// TODO(developer): Define your own computations
const {lightComputation, heavyComputation} = require('./computations');

// Global (instance-wide) scope
// This computation runs once (at instance cold-start)
const instanceVar = heavyComputation();

/**
 * HTTP function that declares a variable.
 *
 * @param {Object} req request context.
 * @param {Object} res response context.
 */
functions.http('scopeDemo', (req, res) => {
  // Per-function scope
  // This computation runs every time this function is called
  const functionVar = lightComputation();

  res.send(`Per instance: ${instanceVar}, per function: ${functionVar}`);
});

Python

import time

import functions_framework


# Placeholder
def heavy_computation():
    return time.time()


# Placeholder
def light_computation():
    return time.time()


# Global (instance-wide) scope
# This computation runs at instance cold-start
instance_var = heavy_computation()


@functions_framework.http
def scope_demo(request):
    """
    HTTP Cloud Function that declares a variable.
    Args:
        request (flask.Request): The request object.
        <http://flask.pocoo.org/docs/1.0/api/#flask.Request>
    Returns:
        The response text, or any set of values that can be turned into a
        Response object using `make_response`
        <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>.
    """

    # Per-function scope
    # This computation runs every time this function is called
    function_var = light_computation()
    return f"Instance: {instance_var}; function: {function_var}"

Go


// h is in the global (instance-wide) scope.
var h string

// init runs during package initialization. So, this will only run during an
// an instance's cold start.
func init() {
	h = heavyComputation()
	functions.HTTP("ScopeDemo", ScopeDemo)
}

// ScopeDemo is an example of using globally and locally
// scoped variables in a function.
func ScopeDemo(w http.ResponseWriter, r *http.Request) {
	l := lightComputation()
	fmt.Fprintf(w, "Global: %q, Local: %q", h, l)
}

Java


import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;

public class Scopes implements HttpFunction {
  // Global (instance-wide) scope
  // This computation runs at instance cold-start.
  // Warning: Class variables used in functions code must be thread-safe.
  private static final int INSTANCE_VAR = heavyComputation();

  @Override
  public void service(HttpRequest request, HttpResponse response)
      throws IOException {
    // Per-function scope
    // This computation runs every time this function is called
    int functionVar = lightComputation();

    var writer = new PrintWriter(response.getWriter());
    writer.printf("Instance: %s; function: %s", INSTANCE_VAR, functionVar);
  }

  private static int lightComputation() {
    int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    return Arrays.stream(numbers).sum();
  }

  private static int heavyComputation() {
    int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    return Arrays.stream(numbers).reduce((t, x) -> t * x).getAsInt();
  }
}

Ruby

# Global (instance-wide) scope.
# This block runs on cold start, before any function is invoked.
#
# Note: It is usually best to run global initialization in an on_startup block
# instead at the top level of the Ruby file. This is because top-level code
# could be executed to verify the function during deployment, whereas an
# on_startup block is run only when an actual function instance is starting up.
FunctionsFramework.on_startup do
  instance_data = perform_heavy_computation

  # To pass data into function invocations, the best practice is to set a
  # key-value pair using the Ruby Function Framework's built-in "set_global"
  # method. Functions can call the "global" method to retrieve the data by key.
  # (You can also use Ruby global variables or "toplevel" local variables, but
  # they can make it difficult to isolate global data for testing.)
  set_global :my_instance_data, instance_data
end

FunctionsFramework.http "tips_scopes" do |_request|
  # Per-function scope.
  # This method is called every time this function is called.
  invocation_data = perform_light_computation

  # Retrieve the data computed by the on_startup block.
  instance_data = global :my_instance_data

  "instance: #{instance_data}; function: #{invocation_data}"
end

Sie können globale Variablen als Leistungsoptimierung verwenden. Sie dürfen sich jedoch bei vorherigen Funktionsaufrufen nicht auf den im globalen Bereich festgelegten Status verlassen. Weitere Informationen finden Sie unter Zustandslosigkeit.

Sie können davon ausgehen, dass für jede Funktionsinstanz der globale Geltungsbereich genau einmal ausgeführt wurde, bevor Ihr Funktionscode aufgerufen wird. Sie dürfen jedoch nicht von der Gesamtzahl oder dem Zeitpunkt der Ausführungen im globalen Bereich abhängig sein, da diese je nach Autoscaling-Aktivität variieren können.

Zeitlicher Ablauf der Funktionsausführung

Eine Funktion hat nur für die Dauer der Funktionsausführung Zugriff auf die zugewiesenen Ressourcen (Speicher und CPU). Code, der außerhalb des Ausführungszeitraums ausgeführt wird, wird nicht garantiert ausgeführt und kann jederzeit angehalten werden. Daher sollten Sie das Ende der Ausführung der Funktion immer korrekt signalisieren und vermeiden, dass Code darüber hinaus ausgeführt wird. Weitere Informationen finden Sie unter HTTP-Funktionen, Hintergrundfunktionen und CloudEvent-Funktionen.

Die Funktionsausführung unterliegt auch der Zeitüberschreitung der Funktion. Weitere Informationen finden Sie unter Funktionszeitlimit.

Berücksichtigen Sie bei der Initialisierung Ihrer Anwendung den zeitlichen Ablauf der Ausführung. Hintergrundaufgaben sollten während der Initialisierung nicht im globalen Bereich erstellt werden, da sie außerhalb der Dauer einer Anfrage ausgeführt werden.

Ausführungsgarantien

Eine Funktion wird normalerweise einmal für jedes eingehende Ereignis aufgerufen. Cloud Run Functions kann den einmaligen Aufruf aufgrund von Unterschieden in den Fehlerszenarien aber nicht in allen Fällen garantieren.

Die maximale oder minimale Häufigkeit, mit der eine Funktion für ein einzelnes Ereignis aufgerufen werden kann, hängt von ihrem Typ ab:

  • HTTP-Funktionen werden höchstens einmal aufgerufen. Das liegt daran, dass HTTP-Aufrufe synchron erfolgen. Jeder Fehler, der während des Funktionsaufrufs auftritt, wird ohne einen erneuten Versuch zurückgegeben. Es wird erwartet, dass der Aufrufer der HTTP-Funktion die Fehler behandelt und bei Bedarf den Aufruf wiederholt.

  • Ereignisgesteuerte Funktionen werden mindestens einmal aufgerufen. Das liegt an der asynchronen Behandlung von Ereignissen, bei denen kein Aufrufer auf die Antwort wartet. In seltenen Fällen kann es vorkommen, dass das System eine ereignisgesteuerte Funktion mehr als einmal aufruft, um die Zustellung des Ereignisses sicherzustellen. Wenn ein ereignisbasierter Funktionsaufruf mit einem Fehler fehlschlägt, wird die Funktion nur dann wieder aufgerufen, wenn für diese Funktion Wiederholungsversuche bei Fehlern aktiviert sind.

Damit sich die Funktion bei wiederholten Ausführungsversuchen korrekt verhält, sollten Sie sie idempotent machen, indem Sie sie so implementieren, dass die gewünschten Ergebnisse (und Nebeneffekte) auch dann erzeugt werden, wenn ein Ereignis mehrmals bereitgestellt wird. Für HTTP-Funktionen bedeutet das, dass der gewünschte Wert geliefert wird, selbst wenn der Aufrufer die Aufrufe an den HTTP-Funktionsendpunkt wiederholt. Weitere Informationen dazu, wie Sie Ihre Funktion idempotent machen, finden Sie unter Ereignisgesteuerte Funktionen wiederholen.

Speicher- und Dateisystem

Jeder Funktion ist eine bestimmte Menge an Arbeitsspeicher zugewiesen. Sie können die Speichermenge während der Bereitstellung konfigurieren. Weitere Informationen finden Sie unter Speicherlimits.

Die Funktionsausführungsumgebung enthält ein speicherinternes Dateisystem, das die mit Ihrer Funktion bereitgestellten Quelldateien und Verzeichnisse enthält (siehe Quellcode strukturieren). Das Verzeichnis mit den Quelldateien ist schreibgeschützt, der Rest des Dateisystems ist jedoch beschreibbar (außer für Dateien, die vom Betriebssystem verwendet werden). Die Verwendung des Dateisystems wird auf die Speichernutzung einer Funktion angerechnet.

Ihre Funktion kann mithilfe von Standardmethoden in jeder Programmiersprache mit dem Dateisystem interagieren.

Netzwerk

Die Funktion kann über Standardmethoden in jeder Programmiersprache auf das öffentliche Internet zugreifen, sei es über integrierte Bibliotheken, die von den Laufzeitbibliotheken oder Drittanbieterbibliotheken angeboten werden, die Sie als Abhängigkeiten hinzufügen.

Versuchen Sie, Netzwerkverbindungen in mehreren Funktionsaufrufen wiederzuverwenden, wie unter Netzwerke optimieren beschrieben. Eine Verbindung, die 10 Minuten lang nicht verwendet wurde, wird vom System möglicherweise geschlossen. Weitere Versuche, eine geschlossene Verbindung zu verwenden, führen zu einem Fehler "Verbindung zurückgesetzt". Ihr Code sollte daher entweder eine Bibliothek verwenden, die geschlossene Verbindungen verarbeiten kann, oder diese explizit behandeln, wenn Netzwerkkonstrukte auf niedriger Ebene verwendet werden.

Funktionsisolation

Jede bereitgestellte Funktion ist von allen anderen Funktionen isoliert, selbst wenn diese von derselben Quelldatei stammen. Sie teilen weder Arbeitsspeicher, globale Variablen, Dateisysteme noch andere Zustände.

Zur Freigabe von Daten für alle bereitgestellten Funktionen können Sie Dienste wie Memorystore, Datastore, Firestore oder Cloud Storage verwenden. Alternativ können Sie mit den entsprechenden Triggern eine Funktion aus einer anderen aufrufen und die erforderlichen Daten weitergeben. Führen Sie zum Beispiel eine HTTP-Anfrage an den Endpunkt einer HTTP-Funktion aus oder veröffentlichen Sie eine Nachricht an ein Pub- / Sub-Thema, um eine Pub/Sub-Funktion auszulösen.