Gérer les fonctions


Vous pouvez déployer, supprimer et modifier des fonctions à l'aide des commandes CLI Firebase ou en définissant des options d'exécution dans le code source de vos fonctions.

Déployer des fonctions

Pour déployer des fonctions, exécutez cette commande Firebase CLI :

firebase deploy --only functions

Par défaut, la CLI Firebase déploie toutes les fonctions de votre source en même temps. Si votre projet contient plus de 5 fonctions, nous vous recommandons d'utiliser l'indicateur --only avec des noms de fonctions spécifiques pour déployer uniquement les fonctions que vous avez modifiées. Le déploiement de fonctions spécifiques de cette manière accélère le processus de déploiement et vous permet d'éviter de rencontrer des quotas de déploiement. Par exemple:

firebase deploy --only functions:addMessage,functions:makeUppercase

Lors du déploiement d'un grand nombre de fonctions, vous pouvez dépasser le quota standard et recevoir des messages d'erreur HTTP 429 ou 500. Pour résoudre ce problème, déployez les fonctions en groupes de 10 ou moins.

Consultez la référence Firebase CLI pour la liste complète des commandes disponibles.

Par défaut, la CLI Firebase recherche dans le dossier functions/ le code source. Si vous préférez, vous pouvez organiser les fonctions dans des bases de code ou plusieurs ensembles de fichiers.

Supprimer des fonctions

Vous pouvez supprimer les fonctions précédemment déployées de ces manières :

  • explicitement dans la CLI Firebase avec functions:delete
  • explicitement dans la console Google Cloud .
  • implicitement en supprimant la fonction de la source avant le déploiement.

Toutes les opérations de suppression vous demandent de confirmer avant de supprimer la fonction de la production.

La suppression explicite de fonctions dans la CLI Firebase prend en charge plusieurs arguments ainsi que des groupes de fonctions et vous permet de spécifier une fonction exécutée dans une région particulière. Vous pouvez également remplacer l'invite de confirmation.

# Delete all functions that match the specified name in all regions.
firebase functions:delete myFunction
# Delete a specified function running in a specific region.
firebase functions:delete myFunction --region us-east-1
# Delete more than one function
firebase functions:delete myFunction myOtherFunction
# Delete a specified functions group.
firebase functions:delete groupA
# Bypass the confirmation prompt.
firebase functions:delete myFunction --force

Avec la suppression implicite des fonctions, firebase deploy analyse votre source et supprime de la production toutes les fonctions qui ont été supprimées du fichier.

Modifier le nom, la région ou le déclencheur d'une fonction

Si vous renommez ou modifiez les régions ou déclenchez des fonctions qui gèrent le trafic de production, suivez les étapes de cette section pour éviter de perdre des événements lors de la modification. Avant de suivre ces étapes, assurez-vous d'abord que votre fonction est idempotente , car la nouvelle version et l'ancienne version de votre fonction s'exécuteront en même temps pendant le changement.

Renommer une fonction

Pour renommer une fonction, créez une nouvelle version renommée de la fonction dans votre source, puis exécutez deux commandes de déploiement distinctes. La première commande déploie la fonction nouvellement nommée et la deuxième commande supprime la version précédemment déployée. Par exemple, si vous souhaitez renommer un webhook déclenché par HTTP, révisez le code comme suit :

Noeud.js

// before
const {onRequest}  = require('firebase-functions/v2/https');

exports.webhook = onRequest((req, res) => {
    res.send("Hello");
});

// after
const {onRequest}  = require('firebase-functions/v2/https');

exports.webhookNew = onRequest((req, res) => {
    res.send("Hello");
});

Python

# before
from firebase_functions import https_fn

@https_fn.on_request()
def webhook(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

# after
from firebase_functions import https_fn

@https_fn.on_request()
def webhook_new(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

Exécutez ensuite les commandes suivantes pour déployer la nouvelle fonction :

# Deploy new function
firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both functions are running

# Delete webhook
firebase functions:delete webhook

Modifier la ou les régions d'une fonction

Si vous modifiez les régions spécifiées pour une fonction qui gère le trafic de production, vous pouvez éviter la perte d'événements en effectuant ces étapes dans l'ordre :

  1. Renommez la fonction et modifiez sa ou ses régions comme vous le souhaitez.
  2. Déployez la fonction renommée, ce qui entraîne l'exécution temporaire du même code dans les deux ensembles de régions.
  3. Supprimez la fonction précédente.

Par exemple, si vous disposez d'une fonction déclenchée par Cloud Firestore qui se trouve actuellement dans la région des fonctions par défaut de us-central1 et que vous souhaitez la migrer vers asia-northeast1 , vous devez d'abord modifier votre code source pour renommer la fonction et réviser la région.

Noeud.js

// before
exports.firestoreTrigger = onDocumentCreated(
  "my-collection/{docId}",
  (event) => {},
);

// after
exports.firestoreTriggerAsia = onDocumentCreated(
  {
    document: "my-collection/{docId}",
    region: "asia-northeast1",
  },
  (event) => {},
);

Le code mis à jour doit spécifier le filtre d'événements correct (dans ce cas, document ) ainsi que la région. Consultez les emplacements Cloud Functions pour plus d’informations.

Python

# Before
@firestore_fn.on_document_created("my-collection/{docId}")
def firestore_trigger(event):
    pass

# After
@firestore_fn.on_document_created("my-collection/{docId}",
                                  region="asia-northeast1")
def firestore_trigger_asia(event):
    pass

Déployez ensuite en exécutant :

firebase deploy --only functions:firestoreTriggerAsia

Deux fonctions identiques sont désormais en cours d'exécution : firestoreTrigger s'exécute dans us-central1 et firestoreTriggerAsia s'exécute dans asia-northeast1 .

Ensuite, supprimez firestoreTrigger :

firebase functions:delete firestoreTrigger

Il n'y a désormais qu'une seule fonction - firestoreTriggerAsia , qui s'exécute dans asia-northeast1 .

Changer le type de déclencheur d'une fonction

Au fur et à mesure que vous développez votre déploiement Cloud Functions pour Firebase au fil du temps, vous devrez peut-être modifier le type de déclencheur d'une fonction pour diverses raisons. Par exemple, vous souhaiterez peut-être passer d'un type d'événement Firebase Realtime Database ou Cloud Firestore à un autre type.

Il n'est pas possible de modifier le type d'événement d'une fonction en modifiant simplement le code source et en exécutant firebase deploy . Pour éviter les erreurs, modifiez le type de déclencheur d'une fonction en suivant cette procédure :

  1. Modifiez le code source pour inclure une nouvelle fonction avec le type de déclencheur souhaité.
  2. Déployez la fonction, ce qui entraîne l'exécution temporaire des anciennes et des nouvelles fonctions.
  3. Supprimez explicitement l'ancienne fonction de la production à l'aide de la CLI Firebase.

Par exemple, si vous aviez une fonction qui était déclenchée lorsqu'un objet était supprimé, mais que vous avez ensuite activé la gestion des versions d'objet et que vous souhaitez plutôt vous abonner à l'événement d'archive, renommez d'abord la fonction et modifiez-la pour avoir le nouveau type de déclencheur.

Noeud.js

// before
const {onObjectDeleted} = require("firebase-functions/v2/storage");

exports.objectDeleted = onObjectDeleted((event) => {
    // ...
});

// after
const {onObjectArchived} = require("firebase-functions/v2/storage");

exports.objectArchived = onObjectArchived((event) => {
    // ...
});

Python

# before
from firebase_functions import storage_fn

@storage_fn.on_object_deleted()
def object_deleted(event):
  # ...

# after 
from firebase_functions import storage_fn

@storage_fn.on_object_archived()
def object_archived(event):
  # ...

Exécutez ensuite les commandes suivantes pour créer d'abord la nouvelle fonction, avant de supprimer l'ancienne fonction :

# Create new function objectArchived
firebase deploy --only functions:objectArchived

# Wait until deployment is done; now both objectDeleted and objectArchived are running

# Delete objectDeleted
firebase functions:delete objectDeleted

Définir les options d'exécution

Cloud Functions pour Firebase vous permet de sélectionner des options d'exécution telles que la version d'exécution de Node.js et le délai d'expiration par fonction, l'allocation de mémoire et les instances de fonction minimales/maximales.

Il est recommandé de définir ces options (sauf pour la version Node.js) sur un objet de configuration à l'intérieur du code de fonction. Cet objet RuntimeOptions est la source fiable des options d'exécution de votre fonction et remplacera les options définies via toute autre méthode (telle que via la console Google Cloud ou gcloud CLI).

Si votre flux de travail de développement implique la définition manuelle des options d'exécution via la console Google Cloud ou gcloud CLI et que vous ne souhaitez pas que ces valeurs soient remplacées à chaque déploiement, définissez l'option preserveExternalChanges sur true . Avec cette option définie sur true , Firebase fusionne les options d'exécution définies dans votre code avec les paramètres de la version actuellement déployée de votre fonction avec la priorité suivante :

  1. L'option est définie dans le code des fonctions : remplacer les modifications externes.
  2. L'option est définie sur RESET_VALUE dans le code des fonctions : remplacez les modifications externes par la valeur par défaut.
  3. L'option n'est pas définie dans le code des fonctions, mais est définie dans la fonction actuellement déployée : utilisez l'option spécifiée dans la fonction déployée.

L’utilisation de l’option preserveExternalChanges: true n’est pas recommandée pour la plupart des scénarios, car votre code ne sera plus la source complète de vérité pour les options d’exécution de vos fonctions. Si vous l'utilisez, consultez la console Google Cloud ou utilisez gcloud CLI pour afficher la configuration complète d'une fonction.

Définir la version de Node.js

Le SDK Firebase pour Cloud Functions permet une sélection du runtime Node.js. Vous pouvez choisir d'exécuter toutes les fonctions d'un projet exclusivement sur l'environnement d'exécution correspondant à l'une de ces versions de Node.js prises en charge :

  • Node.js 20 (aperçu)
  • Node.js 18
  • Node.js 16
  • Noeud.js 14

Pour définir la version de Node.js :

Vous pouvez définir la version dans le champ engines du fichier package.json qui a été créé dans votre répertoire functions/ lors de l'initialisation. Par exemple, pour utiliser uniquement la version 18, éditez cette ligne dans package.json :

  "engines": {"node": "18"}

Si vous utilisez le gestionnaire de packages Yarn ou si vous avez d'autres exigences spécifiques pour le champ engines , vous pouvez plutôt définir le temps d'exécution du SDK Firebase pour Cloud Functions dans firebase.json :

  {
    "functions": {
      "runtime": "nodejs18" // or nodejs14, nodejs16 or nodejs20
    }
  }

La CLI utilise la valeur définie dans firebase.json de préférence à toute valeur ou plage que vous définissez séparément dans package.json .

Mettez à niveau votre environnement d'exécution Node.js

Pour mettre à niveau votre environnement d'exécution Node.js :

  1. Assurez-vous que votre projet est sur le plan tarifaire Blaze .
  2. Assurez-vous que vous utilisez Firebase CLI v11.18.0 ou une version ultérieure.
  3. Modifiez la valeur engines dans le fichier package.json qui a été créé dans votre répertoire functions/ lors de l'initialisation. Par exemple, si vous effectuez une mise à niveau de la version 16 vers la version 18, l'entrée devrait ressembler à ceci : "engines": {"node": "18"}
  4. Vous pouvez éventuellement tester vos modifications à l'aide de Firebase Local Emulator Suite .
  5. Redéployez toutes les fonctions.

Définir la version de Python

Le SDK Firebase pour Cloud Functions versions 12.0.0 et supérieures permet la sélection du runtime Python. Définissez la version d'exécution dans firebase.json comme indiqué :

  {
    "functions": {
      "runtime": "python310" // or python311
    }
  }

Contrôler le comportement de mise à l'échelle

Par défaut, Cloud Functions pour Firebase adapte le nombre d'instances en cours d'exécution en fonction du nombre de requêtes entrantes, pouvant potentiellement atteindre zéro instance en période de trafic réduit. Toutefois, si votre application nécessite une latence réduite et que vous souhaitez limiter le nombre de démarrages à froid, vous pouvez modifier ce comportement par défaut en spécifiant un nombre minimum d'instances de conteneur à maintenir au chaud et prêtes à répondre aux demandes.

De même, vous pouvez définir un nombre maximum pour limiter la mise à l'échelle des instances en réponse aux demandes entrantes. Utilisez ce paramètre pour contrôler vos coûts ou pour limiter le nombre de connexions à un service de support tel qu'une base de données.

En utilisant ces paramètres avec le paramètre de simultanéité par instance (nouveau dans la 2e génération), vous pouvez contrôler et ajuster le comportement de mise à l'échelle de vos fonctions. La nature de votre application et de votre fonction déterminera quels paramètres sont les plus rentables et donneront les meilleures performances.

Pour certaines applications à faible trafic, une option de processeur inférieure sans multi-concurrence est optimale. Pour d'autres, où les démarrages à froid constituent un problème critique, la définition d'une concurrence élevée et d'un minimum d'instances signifie qu'un ensemble d'instances est toujours maintenu au chaud pour gérer les pics de trafic importants.

Pour les applications à plus petite échelle qui reçoivent très peu de trafic, la définition d'un nombre maximal d'instances faible avec une simultanéité élevée signifie que l'application peut gérer des rafales de trafic sans encourir de coûts excessifs. Cependant, gardez à l’esprit que lorsque le nombre maximum d’instances est trop bas, les requêtes peuvent être abandonnées lorsque le plafond est atteint.

Autoriser les demandes simultanées

Dans Cloud Functions pour Firebase (1re génération), chaque instance pouvait gérer une requête à la fois. Le comportement de mise à l'échelle était donc défini uniquement avec les paramètres minimum et maximum des instances. En plus de contrôler le nombre d'instances, dans Cloud Functions pour Firebase (2e génération), vous pouvez contrôler le nombre de requêtes que chaque instance peut traiter en même temps grâce à l'option concurrency . La valeur par défaut de la simultanéité est 80, mais vous pouvez la définir sur n'importe quel nombre entier compris entre 1 et 1 000.

Les fonctions avec des paramètres de concurrence plus élevés peuvent absorber les pics de trafic sans démarrage à froid, car chaque instance dispose probablement d'une certaine marge. Si une instance est configurée pour gérer jusqu'à 50 requêtes simultanées mais n'en traite actuellement que 25, elle peut gérer un pic de 25 requêtes supplémentaires sans nécessiter le démarrage à froid d'une nouvelle instance. En revanche, avec un paramètre de concurrence de seulement 1, ce pic de requêtes pourrait conduire à 25 démarrages à froid.

Ce scénario simplifié démontre les gains d’efficacité potentiels de la concurrence. En réalité, faire évoluer le comportement pour optimiser l’efficacité et réduire les démarrages à froid avec concurrence est plus complexe. La concurrence dans Cloud Functions pour Firebase 2e génération est optimisée par Cloud Run et suit les règles de Cloud Run en matière de mise à l'échelle automatique des instances de conteneur .

Lorsque vous expérimentez des paramètres de simultanéité plus élevés dans Cloud Functions pour Firebase (2e génération), gardez les points suivants à l'esprit :

  • Des paramètres de concurrence plus élevés peuvent nécessiter un processeur et une RAM plus élevés pour des performances optimales jusqu'à atteindre une limite pratique. Une fonction qui effectue un traitement intensif d'images ou de vidéos, par exemple, peut ne pas disposer des ressources nécessaires pour gérer 1 000 requêtes simultanées, même lorsque ses paramètres de processeur et de RAM sont maximisés.
  • Étant donné que Cloud Functions pour Firebase (2e génération) est alimenté par Cloud Run, vous pouvez également vous référer aux conseils de Google Cloud pour optimiser la simultanéité .
  • Assurez-vous de tester minutieusement la multiconcurrence dans un environnement de test avant de passer à la multiconcurrence en production.

Gardez un minimum d'instances au chaud

Vous pouvez définir le nombre minimum d'instances pour une fonction dans le code source. Par exemple, cette fonction définit un minimum de 5 instances pour garder au chaud :

Noeud.js

const { onCall } = require("firebase-functions/v2/https");

exports.getAutocompleteResponse = onCall(
  {
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  },
  (event) => {
    // Autocomplete user’s search term
  }
);

Python

@https_fn.on_call(min_instances=5)
def get_autocomplete_response(event: https_fn.CallableRequest) -> https_fn.Response:

Voici quelques éléments à prendre en compte lors de la définition d'une valeur minimale d'instance :

  • Si Cloud Functions pour Firebase fait évoluer votre application au-dessus de vos paramètres, vous subirez un démarrage à froid pour chaque instance au-dessus de ce seuil.
  • Les démarrages à froid ont l'effet le plus grave sur les applications dont le trafic est intense. Si votre application présente des pics de trafic et que vous définissez une valeur suffisamment élevée pour réduire les démarrages à froid à chaque augmentation de trafic, vous constaterez une latence considérablement réduite. Pour les applications avec un trafic constant, les démarrages à froid ne risquent pas d’affecter gravement les performances.
  • La définition d'instances minimales peut avoir du sens pour les environnements de production, mais doit généralement être évitée dans les environnements de test. Pour atteindre zéro dans votre projet de test tout en réduisant les démarrages à froid dans votre projet de production, vous pouvez définir une valeur minimale d'instances dans votre configuration paramétrée :

    Noeud.js

    const functions = require('firebase-functions');
    const { defineInt, defineString } = require('firebase-functions/params');
    
    // Define some parameters
    const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
    const welcomeMessage = defineString('WELCOME_MESSAGE');
    
    // To use configured parameters inside the config for a function, provide them 
    // directly. To use them at runtime, call .value() on them.
    export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
      (req, res) => {
        res.send(`${welcomeMessage.value()}! I am a function.`);
      }
    );
    

    Python

    MIN_INSTANCES = params.IntParam("HELLO_WORLD_MININSTANCES")
    WELCOME_MESSAGE = params.StringParam("WELCOME_MESSAGE")
    
    @https_fn.on_request(min_instances=MIN_INSTANCES.value())
    def get_autocomplete_response(event: https_fn.Request) -> https_fn.Response:
        return https_fn.Response(f"{WELCOME_MESSAGE.value()} I'm a function.")
    

Limiter le nombre maximum d'instances pour une fonction

Vous pouvez définir une valeur pour le nombre maximal d'instances dans le code source de la fonction. Par exemple, cette fonction fixe une limite de 100 instances afin de ne pas surcharger une hypothétique base de données existante :

Noeud.js

const { onMessagePublished } = require("firebase-functions/v2/pubsub");

exports.mirrorevents = onMessagePublished(
  { topic: "topic-name", maxInstances: 100 },
  (event) => {
    // Connect to legacy database
  }
);

Python

@pubsub_fn.on_message_published(topic="topic-name", max_instances=100)
def mirrorevents(event: pubsub_fn.CloudEvent):
#  Connect to legacy database

Si une fonction HTTP est mise à l'échelle jusqu'à la limite maximale d'instances, les nouvelles requêtes sont mises en file d'attente pendant 30 secondes, puis rejetées avec un code de réponse de 429 Too Many Requests si aucune instance n'est disponible à ce moment-là.

Pour en savoir plus sur les bonnes pratiques d'utilisation des paramètres de nombre maximal d'instances, consultez ces bonnes pratiques pour définir le nombre maximal d'instances .

Définir le délai d'attente et l'allocation de mémoire

Dans certains cas, vos fonctions peuvent avoir des exigences particulières en matière de valeur de délai d'attente longue ou d'allocation de mémoire importante. Vous pouvez définir ces valeurs soit dans la console Google Cloud, soit dans le code source de la fonction (Firebase uniquement).

Pour définir l'allocation de mémoire et le délai d'expiration dans le code source des fonctions, utilisez les options globales pour les secondes de mémoire et de délai d'expiration pour personnaliser la machine virtuelle exécutant vos fonctions. Par exemple, cette fonction Cloud Storage utilise 1 Go de mémoire et expire après 300 secondes :

Noeud.js

exports.convertLargeFile = onObjectFinalized({
  timeoutSeconds: 300,
  memory: "1GiB",
}, (event) => {
  // Do some complicated things that take a lot of memory and time
});

Python

@storage_fn.on_object_finalized(timeout_sec=300, memory=options.MemoryOption.GB_1)
def convert_large_file(event: storage_fn.CloudEvent):
# Do some complicated things that take a lot of memory and time.

La valeur maximale des secondes d'expiration est 540 ou 9 minutes.

Pour définir l'allocation de mémoire et le délai d'expiration dans la console Google Cloud :

  1. Dans la console Google Cloud, sélectionnez Cloud Functions pour Firebase dans le menu de gauche.
  2. Sélectionnez une fonction en cliquant sur son nom dans la liste des fonctions.
  3. Cliquez sur l'icône Modifier dans le menu supérieur.
  4. Sélectionnez une allocation de mémoire dans le menu déroulant intitulé Mémoire allouée .
  5. Cliquez sur Plus pour afficher les options avancées et entrez un nombre de secondes dans la zone de texte Délai d'expiration .
  6. Cliquez sur Enregistrer pour mettre à jour la fonction.

Remplacer les paramètres par défaut du processeur

Jusqu'à 2 Go de mémoire allouée, chaque fonction de Cloud Functions pour Firebase (2e génération) utilise par défaut un processeur, puis passe à 2 processeurs pour 4 et 8 Go. Notez que cela diffère considérablement du comportement par défaut de la première génération, ce qui pourrait entraîner des coûts légèrement plus élevés pour les fonctions à faible mémoire, comme indiqué dans le tableau suivant :

RAM allouée CPU par défaut de la version 1 (fractionnaire) Processeur par défaut de la version 2 Augmentation du prix par ms
128 Mo 1/12 1 10,5x
256 Mo 1/6 1 5,3x
512 Mo 1/3 1 2,7x
1 Go 7/12 1 1,6x
2 Go 1 1 1 fois
4 Go 2 2 1 fois
8 Go 2 2 1 fois
16 GB n / A 4 n / A

Si vous préférez le comportement de 1re génération pour vos fonctions de 2e génération, définissez les valeurs par défaut de 1re génération comme option globale :

Noeud.js

// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcf_gen1' });

Python

# Use 1st gen behavior
set_global_options(cpu="gcf_gen1")

Pour les fonctions gourmandes en CPU, la 2e génération offre la flexibilité de configurer un CPU supplémentaire. Vous pouvez augmenter le CPU fonction par fonction, comme indiqué :

Noeud.js

// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
  // computer vision goes here
});

Python

# Boost CPU in a function:
@storage_fn.on_object_finalized(cpu=2)
def analyze_image(event: storage_fn.CloudEvent):
# computer vision goes here