Environnement d'exécution Cloud Functions

Les fonctions Cloud Run s'exécutent dans un environnement sans serveur entièrement géré, dans lequel Google gère l'infrastructure, les systèmes d'exploitation et les environnements d'exécution. Chaque fonction Cloud Functions s'exécute dans son propre contexte sécurisé et isolé, évolue automatiquement et dispose d'un cycle de vie indépendant des autres fonctions.

Environnements d'exécution

Cloud Run Functions acceptent plusieurs environnements d'exécution de langage. Chaque package contient un ensemble standard de packages système, ainsi que les outils et bibliothèques nécessaires pour ce langage. Vous aurez besoin de la valeur de l'ID d'exécution si vous déployez des fonctions à partir de la ligne de commande ou via Terraform.

Les mises à jour de sécurité et de maintenance sont disponibles pour tous les environnements d'exécution de 1re et 2e générations. Ces mises à jour sont appliquées automatiquement ou manuellement, en fonction de l'environnement et de la manière dont vous l'avez configuré. Pour en savoir plus sur les mises à jour de l'environnement d'exécution, consultez la page Sécuriser votre fonction Cloud Run.

Node.js

Environnement d'exécution Génération Environnement ID d'exécution Image de l'environnement d'exécution
Node.js 22 2e génération Ubuntu 22.04 nodejs22 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs22
Node.js 20 1st gen, 2nd gen Ubuntu 22.04 nodejs20 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs20
Node.js 18 1st gen, 2nd gen Ubuntu 22.04 nodejs18 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/nodejs18
Node.js 16 1st gen, 2nd gen Ubuntu 18.04 Node.js 16 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs16
Node.js 14 1st gen, 2nd gen Ubuntu 18.04 nodejs14 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs14
Node.js 12 1st gen, 2nd gen Ubuntu 18.04 nodejs12 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs12
Node.js 10 1st gen, 2nd gen Ubuntu 18.04 nodejs10 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/nodejs10
Node.js 8 1st gen, 2nd gen Ubuntu 18.04 nodejs8 Hors service
Node.js 6 1st gen, 2nd gen Ubuntu 18.04 nodejs6 Hors service

Python

Environnement d'exécution Génération Environnement ID d'exécution Image de l'environnement d'exécution
Python 3.12 1st gen, 2nd gen Ubuntu 22.04 python312 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python312
Python 3.11 1st gen, 2nd gen Ubuntu 22.04 python311 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python311
Python 3.10 1st gen, 2nd gen Ubuntu 22.04 python310 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/python310
Python 3.9 1st gen, 2nd gen Ubuntu 18.04 python39 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python39
Python 3.8 1st gen, 2nd gen Ubuntu 18.04 python38 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python38
Python 3.7 1re génération Ubuntu 18.04 python37 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/python37

Go

Environnement d'exécution Génération Environnement ID d'exécution Image de l'environnement d'exécution
Go 1.23
(bêta uniquement)
2e génération Ubuntu 22.04 go123 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go123
Go 1.22 2e génération Ubuntu 22.04 go122 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go122
Go 1.21 1st gen, 2nd gen Ubuntu 22.04 go121 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go121
Go 1.20 1st gen, 2nd gen Ubuntu 22.04 go120 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go120
Go 1.19 1st gen, 2nd gen Ubuntu 22.04 go119 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go119
Go 1.18 1st gen, 2nd gen Ubuntu 22.04 go118 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/go118
Go 1.16 1st gen, 2nd gen Ubuntu 18.04 go116 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go116
Go 1.13 1st gen, 2nd gen Ubuntu 18.04 go113 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/go113
Go 1.11 1st gen, 2nd gen Ubuntu 18.04 go111 Hors service

Java

Environnement d'exécution Génération Environnement ID d'exécution Image de l'environnement d'exécution
Java 21 2e génération Ubuntu 22.04 java21 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java21
Java 17 1st gen, 2nd gen Ubuntu 22.04 java17 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/java17
Java 11 1st gen, 2nd gen Ubuntu 18.04 java11 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/java11

Ruby

Environnement d'exécution Génération Environnement ID d'exécution Image de l'environnement d'exécution
Ruby 3.3 1st gen, 2nd gen Ubuntu 22.04 ruby33 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.2 1st gen, 2nd gen Ubuntu 22.04 ruby32 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/ruby32
Ruby 3.0 1st gen, 2nd gen Ubuntu 18.04 ruby30 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby30
Ruby 2.7 1st gen, 2nd gen Ubuntu 18.04 ruby27 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby27
Ruby 2.6 1st gen, 2nd gen Ubuntu 18.04 ruby26 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/ruby26

PHP

Environnement d'exécution Environnement Génération ID d'exécution Image de l'environnement d'exécution
PHP 8.3 2e génération Ubuntu 22.04 php83 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php83
PHP 8.2 1st gen, 2nd gen Ubuntu 22.04 php82 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/php82
PHP 8.1 1st gen, 2nd gen Ubuntu 18.04 php81 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php81
PHP 7.4 1st gen, 2nd gen Ubuntu 18.04 php74 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/php74

.NET Core

Environnement d'exécution Génération Environnement ID d'exécution Image de l'environnement d'exécution
.NET Core 8 2e génération Ubuntu 22.04 dotnet8 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet8
.NET Core 6 1st gen, 2nd gen Ubuntu 22.04 dotnet6 us-central1-docker.pkg.dev/serverless-runtimes/google-22-full/runtimes/dotnet6
.NET Core 3 1st gen, 2nd gen Ubuntu 18.04 dotnet3 us-central1-docker.pkg.dev/serverless-runtimes/google-18-full/runtimes/dotnet3

Comportement d'autoscaling

Cloud Run Functions met en œuvre le paradigme sans serveur, dans lequel vous exécutez simplement votre code sans vous soucier de l'infrastructure sous-jacente, telle que les serveurs ou les machines virtuelles. Une fois déployées, vos fonctions sont automatiquement gérées et adaptées.

Cloud Run Functions gère les requêtes entrantes en les attribuant à des instances de votre fonction. En fonction du volume de requêtes et du nombre d'instances de fonction existantes, Cloud Run Functions peuvent attribuer une requête à une instance existante ou en créer une.

Lorsque le volume de requêtes entrantes dépasse le nombre d'instances existantes, Cloud Run Functions peuvent démarrer plusieurs nouvelles instances pour gérer les requêtes. Ce comportement de scaling automatique permet à Cloud Run Functions de gérer de nombreuses requêtes en parallèle, chacune utilisant une instance différente de votre fonction.

Dans certains cas, un scaling illimité peut être souhaitable. Pour résoudre ce problème, les fonctions Cloud Run vous permettent de configurer un nombre maximal d'instances pouvant coexister à un moment donné pour une fonction particulière.

Caractéristique "sans état"

Pour activer la gestion et le scaling automatiques de vos fonctions, celles-ci doivent être sans état : un appel de fonction ne doit pas dépendre de l'état en mémoire défini par un appel précédent. Les appels peuvent être gérés par différentes instances de fonctions qui ne partagent pas de variables globales, de mémoire, de systèmes de fichiers ou d'autres états.

Si vous avez besoin de partager un état sur l'ensemble des appels de fonctions, votre fonction doit utiliser un service tel que Memorystore, Datastore, Firestore ou Cloud Storage pour conserver ces données. Consultez les pages Bases de données Google Cloud et Produits de stockage Google Cloud pour en savoir plus sur les options de base de données et de stockage proposées par Google Cloud.

Simultanéité

Cloud Run Functions (2nd gen)

Cloud Run Functions (2nd gen) permet de gérer plusieurs requêtes simultanées sur une seule instance de fonction. Cela peut être utile pour éviter les démarrages à froid, car une instance déjà préchauffée peut traiter plusieurs requêtes simultanément, ce qui réduit la latence globale. Pour en savoir plus, consultez la section Simultanéité

Cloud Run Functions (1st gen)

Dans Cloud Run Function (1st gen), chaque instance d'une fonction ne traite qu'une seule requête simultanée à la fois. Cela signifie que lorsque votre code traite une requête, il est impossible qu'une deuxième requête soit acheminée vers la même instance. Ainsi, la requête d'origine peut utiliser la totalité des ressources (mémoire et processeur) que vous allouez.

Étant donné que les requêtes simultanées dans Cloud Run Functions (1st gen) sont traitées par différentes instances de fonctions, elles ne partagent pas les mêmes variables ni la même mémoire locale. Pour en savoir plus, consultez les sections Sans état et Durée de vie de l'instance de fonction.

Démarrages à froid

Une nouvelle instance de fonction est créée dans deux cas :

  • Lorsque vous déployez une fonction.

  • Lorsqu'une nouvelle instance de fonction est automatiquement créée pour s'adapter à la charge actuelle ou, plus rarement, pour remplacer une instance existante.

Le lancement d'une nouvelle instance de fonction implique le chargement de l'environnement d'exécution et de votre code. Les requêtes qui impliquent le démarrage d'une instance de fonction, appelées démarrages à froid, peuvent être plus lentes que les requêtes acheminées vers des instances de fonction existantes. Si votre fonction reçoit une charge constante, le nombre de démarrages à froid est généralement négligeable, à moins que votre fonction connaisse de nombreux plantages et nécessite un redémarrage de tout son environnement.

Si votre code de fonction génère une exception non détectée ou bloque le processus en cours, l'instance de fonction peut être redémarrée. Cela peut entraîner des démarrages à froid plus élevés et une latence plus élevée. Nous vous recommandons donc de capturer les exceptions et d'éviter l'arrêt du processus en cours. Consultez la page Signaler des erreurs pour savoir comment gérer et signaler les erreurs dans Cloud Run Functions.

Si votre fonction est sensible à la latence, envisagez de définir un nombre minimal d'instances pour éviter les démarrages à froid.

Durée de vie de l'instance de fonction

Les instances de fonction sont généralement résilientes et réutilisées par des appels de fonctions ultérieurs, à moins que le nombre d'instances soit réduit en raison d'un manque de trafic continu ou de plantage de votre fonction. Cela signifie que lorsque l'exécution d'une fonction se termine, un autre appel de fonction peut être géré par cette même instance de fonction.

Champ d'application de la fonction et champ d'application global

Un appel de fonction unique entraîne seulement l'exécution du corps de la fonction déclarée comme point d'entrée. Le champ d'application global de votre code source de fonction n'est exécuté que lors de démarrages à froid, et non sur des instances déjà initialisées.

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

Vous pouvez utiliser des variables globales à des fins d'optimisation, mais vous ne devez pas vous fier à l'état défini dans le champ d'application global par les appels de fonctions précédents. Pour plus d'informations, consultez la page Sans état.

Vous pouvez considérer que pour chaque instance de fonction, le champ d'application global aura été exécuté une fois avant que votre code de fonction ne soit appelé. Toutefois, vous ne devez pas dépendre du nombre total d'exécutions de champ d'application global, ni de leur planification, car elles peuvent varier en fonction de l'activité de l'autoscaling.

Chronologie d'exécution des fonctions

Une fonction n'a accès à ses ressources allouées (mémoire et processeur) que pendant sa durée d'exécution. L'exécution du code en dehors de la période d'exécution n'est pas garantie et peut être interrompue à tout moment. Par conséquent, vous devez toujours signaler la fin de l'exécution de votre fonction et éviter d'exécuter du code au-delà. Pour obtenir des conseils, consultez les pages Fonctions HTTP, Fonctions d'arrière-plan et Fonctions CloudEvent.

L'exécution d'une fonction est également soumise à un délai d'inactivité. Pour en savoir plus, consultez la section Délai d'inactivité d'une fonction.

Tenez compte de la chronologie d'exécution lors de l'initialisation de votre application. Les tâches en arrière-plan ne doivent pas être créées dans le champ d'application global lors de l'initialisation, car elles s'exécutent en dehors de la durée d'une requête.

Garanties d'exécution

Vos fonctions sont généralement appelées une seule fois pour chaque événement entrant. Cependant, Cloud Run Functions ne garantit pas un appel unique dans tous les cas, en raison de différences dans les scénarios d'erreur.

Le nombre maximum ou minimum d'appels de fonctions pour un seul événement dépend du type de fonction :

  • Les fonctions HTTP sont appelées au maximum une fois. Cela est dû à la nature synchrone des appels HTTP. Ainsi, toute erreur survenant lors de l'appel de la fonction sera affichée sans nouvelle tentative. L'appelant d'une fonction HTTP doit assumer la gestion des erreurs, ainsi que des nouvelles tentatives, le cas échéant.

  • Les fonctions basées sur des événements sont appelées au moins une fois. Cela est dû à la nature asynchrone de la gestion de ces événements, dans lesquels aucun appelant n'attend de réponse. Dans de rares cas, le système peut appeler plusieurs fois une fonction basée sur des événements, afin d'assurer la diffusion de l'événement. Si un appel de fonction basée sur des événements échoue et renvoie une erreur, cet appel ne sera pas renouvelé, sauf si des tentatives en cas d'échec sont activées pour cette fonction.

Pour vous assurer que votre fonction se comporte correctement lors de nouvelles tentatives d’exécution, vous devez la rendre idempotente en la mettant en œuvre de sorte qu'un événement produise les résultats souhaités (et les effets secondaires), même s’il est transmis plusieurs fois. Dans le cas des fonctions HTTP, cela signifie également renvoyer la valeur souhaitée, même si l'appelant réessaie d'appeler le point de terminaison de la fonction HTTP. Consultez la page Effectuer de nouvelles tentatives d'exécution des fonctions basées sur des événements pour plus d'informations sur la manière de rendre votre fonction idempotente.

Mémoire et système de fichiers

Chaque fonction dispose d'une certaine quantité de mémoire allouée à son utilisation. Vous pouvez configurer la quantité de mémoire au déploiement. Pour en savoir plus, consultez la section Limites de mémoire.

L'environnement d'exécution de fonction inclut un système de fichiers en mémoire contenant les fichiers sources et les répertoires déployés avec votre fonction (voir Structurer le code source). Le répertoire contenant vos fichiers source est en lecture seule, mais le reste du système de fichiers est accessible en écriture (à l'exception des fichiers utilisés par le système d'exploitation). L'utilisation du système de fichiers est comptabilisée dans l'utilisation de la mémoire d'une fonction.

Votre fonction peut interagir avec le système de fichiers à l'aide de méthodes standards dans chaque langage de programmation.

Réseau

Votre fonction peut accéder à l'Internet public en utilisant des méthodes standards dans chaque langage de programmation, que ce soit via des bibliothèques intégrées proposées par l'environnement d'exécution ou des bibliothèques tierces que vous incluez en tant que dépendances.

Essayez de réutiliser les connexions réseau pour vos appels de fonctions, comme décrit dans la section Optimisation des réseaux. Notez toutefois qu'une connexion inutilisée pendant 10 minutes peut être fermée par le système et que toute nouvelle tentative d'utilisation d'une connexion fermée entraîne une erreur de type "Connexion réinitialisée". Votre code doit utiliser une bibliothèque qui gère les connexions fermées de manière appropriée, ou bien les gérer explicitement si vous utilisez des constructions réseau de bas niveau.

Isolation de fonction

Chaque fonction déployée est isolée de toutes les autres fonctions, même celles déployées à partir du même fichier source. Plus précisément, elles ne partagent pas de mémoire, de variables globales, de systèmes de fichiers ou d'autres états.

Pour partager des données entre des fonctions déployées, vous pouvez utiliser des services tels que Memorystore, Datastore, Firestore ou Cloud Storage. Vous pouvez également appeler une fonction à partir d'une autre en utilisant les déclencheurs appropriés et en transmettant les données nécessaires. Par exemple, envoyez une requête HTTP au point de terminaison d'une fonction HTTP ou publiez un message dans un sujet Pub/Sub pour déclencher une fonction Pub/Sub.