Administrar funciones


Puede implementar, eliminar y modificar funciones mediante los comandos de Firebase CLI o configurando opciones de tiempo de ejecución en el código fuente de sus funciones.

Implementar funciones

Para implementar funciones, ejecute este comando de Firebase CLI:

firebase deploy --only functions

De forma predeterminada, Firebase CLI implementa todas las funciones dentro de su fuente al mismo tiempo. Si su proyecto contiene más de 5 funciones, le recomendamos que utilice el indicador --only con nombres de funciones específicos para implementar solo las funciones que ha editado. La implementación de funciones específicas de esta manera acelera el proceso de implementación y le ayuda a evitar toparse con cuotas de implementación. Por ejemplo:

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

Al implementar una gran cantidad de funciones, es posible que supere la cuota estándar y reciba mensajes de error HTTP 429 o 500. Para resolver esto, implemente funciones en grupos de 10 o menos.

Consulte la referencia de Firebase CLI para obtener la lista completa de comandos disponibles.

De forma predeterminada, Firebase CLI busca el código fuente en la carpeta functions/ . Si lo prefiere, puede organizar funciones en bases de código o en múltiples conjuntos de archivos.

Eliminar funciones

Puede eliminar funciones implementadas previamente de estas maneras:

  • explícitamente en Firebase CLI con functions:delete
  • explícitamente en la consola de Google Cloud .
  • implícitamente eliminando la función del código fuente antes de la implementación.

Todas las operaciones de eliminación le solicitan que confirme antes de eliminar la función de producción.

La eliminación explícita de funciones en Firebase CLI admite múltiples argumentos, así como grupos de funciones, y le permite especificar una función que se ejecuta en una región en particular. Además, puede anular el mensaje de confirmación.

# 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

Con la eliminación implícita de funciones, firebase deploy analiza su fuente y elimina de producción cualquier función que se haya eliminado del archivo.

Modificar el nombre, la región o el activador de una función

Si está cambiando el nombre o cambiando las regiones o el activador de funciones que manejan el tráfico de producción, siga los pasos de esta sección para evitar perder eventos durante la modificación. Antes de seguir estos pasos, primero asegúrese de que su función sea idempotente , ya que tanto la versión nueva como la versión anterior de su función se ejecutarán al mismo tiempo durante el cambio.

Cambiar el nombre de una función

Para cambiar el nombre de una función, cree una nueva versión renombrada de la función en su fuente y luego ejecute dos comandos de implementación separados. El primer comando implementa la función recién nombrada y el segundo comando elimina la versión implementada anteriormente. Por ejemplo, si tiene un webhook activado por HTTP al que le gustaría cambiarle el nombre, revise el código de la siguiente manera:

Nodo.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");
});

Pitón

# 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!")

Luego ejecute los siguientes comandos para implementar la nueva función:

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

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

# Delete webhook
firebase functions:delete webhook

Cambiar la región o regiones de una función

Si está cambiando las regiones especificadas para una función que maneja el tráfico de producción, puede evitar la pérdida de eventos realizando estos pasos en orden:

  1. Cambie el nombre de la función y cambie su región o regiones según lo desee.
  2. Implemente la función renombrada, lo que da como resultado la ejecución temporal del mismo código en ambos conjuntos de regiones.
  3. Eliminar la función anterior.

Por ejemplo, si tiene una función activada por Cloud Firestore que se encuentra actualmente en la región de funciones predeterminada de us-central1 y desea migrarla a asia-northeast1 , primero debe modificar su código fuente para cambiar el nombre de la función y revisarla. la región.

Nodo.js

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

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

El código actualizado debe especificar el filtro de eventos correcto (en este caso, document ) junto con la región. Consulte Ubicaciones de Cloud Functions para obtener más información.

Pitón

# 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

Luego implemente ejecutando:

firebase deploy --only functions:firestoreTriggerAsia

Ahora se están ejecutando dos funciones idénticas: firestoreTrigger se ejecuta en us-central1 y firestoreTriggerAsia se ejecuta en asia-northeast1 .

Luego, elimine firestoreTrigger :

firebase functions:delete firestoreTrigger

Ahora solo hay una función: firestoreTriggerAsia , que se ejecuta en asia-northeast1 .

Cambiar el tipo de disparador de una función

A medida que desarrollas tu implementación de Cloud Functions para Firebase con el tiempo, es posible que necesites cambiar el tipo de activador de una función por varios motivos. Por ejemplo, es posible que quieras cambiar de un tipo de evento de Firebase Realtime Database o Cloud Firestore a otro tipo.

No es posible cambiar el tipo de evento de una función simplemente cambiando el código fuente y ejecutando firebase deploy . Para evitar errores, cambie el tipo de activación de una función mediante este procedimiento:

  1. Modifique el código fuente para incluir una nueva función con el tipo de activador deseado.
  2. Implemente la función, lo que da como resultado la ejecución temporal de las funciones nuevas y antiguas.
  3. Elimina explícitamente la función anterior de producción mediante Firebase CLI.

Por ejemplo, si tenía una función que se activaba cuando se eliminaba un objeto, pero luego habilitaba el control de versiones del objeto y deseaba suscribirse al evento de archivo, primero cambie el nombre de la función y edítela para que tenga el nuevo tipo de activador.

Nodo.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) => {
    // ...
});

Pitón

# 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):
  # ...

Luego ejecute los siguientes comandos para crear la nueva función primero, antes de eliminar la función anterior:

# 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

Establecer opciones de tiempo de ejecución

Cloud Functions para Firebase le permite seleccionar opciones de tiempo de ejecución, como la versión de tiempo de ejecución de Node.js y el tiempo de espera por función, la asignación de memoria y las instancias de función mínima/máxima.

Como práctica recomendada, estas opciones (excepto la versión Node.js) deben configurarse en un objeto de configuración dentro del código de la función. Este objeto RuntimeOptions es la fuente de verdad para las opciones de tiempo de ejecución de tu función y anulará las opciones configuradas mediante cualquier otro método (como a través de la consola de Google Cloud o la CLI de gcloud).

Si su flujo de trabajo de desarrollo implica configurar manualmente las opciones de tiempo de ejecución a través de la consola de Google Cloud o la CLI de gcloud y no desea que estos valores se anulen en cada implementación, configure la opción preserveExternalChanges en true . Con esta opción configurada en true , Firebase fusiona las opciones de tiempo de ejecución configuradas en tu código con la configuración de la versión actualmente implementada de tu función con la siguiente prioridad:

  1. La opción está configurada en el código de funciones: anular cambios externos.
  2. La opción está configurada en RESET_VALUE en el código de funciones: anular los cambios externos con el valor predeterminado.
  3. La opción no está configurada en el código de funciones, pero sí en la función implementada actualmente: use la opción especificada en la función implementada.

No se recomienda el uso de la opción preserveExternalChanges: true para la mayoría de los escenarios porque su código ya no será la fuente completa de verdad para las opciones de tiempo de ejecución de sus funciones. Si lo usas, consulta la consola de Google Cloud o usa la CLI de gcloud para ver la configuración completa de una función.

Establecer la versión de Node.js

El SDK de Firebase para Cloud Functions permite una selección del tiempo de ejecución de Node.js. Puede optar por ejecutar todas las funciones de un proyecto exclusivamente en el entorno de ejecución correspondiente a una de estas versiones compatibles de Node.js:

  • Node.js 20 (vista previa)
  • Nodo.js 18
  • Nodo.js 16
  • Nodo.js 14

Para configurar la versión de Node.js:

Puede configurar la versión en el campo engines en el archivo package.json que se creó en su directorio functions/ durante la inicialización. Por ejemplo, para usar solo la versión 18, edite esta línea en package.json :

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

Si está utilizando el administrador de paquetes Yarn o tiene otros requisitos específicos para el campo engines , puede configurar el tiempo de ejecución para Firebase SDK para Cloud Functions en firebase.json :

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

La CLI usa el valor establecido en firebase.json con preferencia a cualquier valor o rango que establezca por separado en package.json .

Actualice su tiempo de ejecución de Node.js

Para actualizar su tiempo de ejecución de Node.js:

  1. Asegúrese de que su proyecto esté en el plan de precios de Blaze .
  2. Asegúrese de estar utilizando Firebase CLI v11.18.0 o posterior.
  3. Cambie el valor engines en el archivo package.json que se creó en su directorio functions/ durante la inicialización. Por ejemplo, si está actualizando de la versión 16 a la versión 18, la entrada debería verse así: "engines": {"node": "18"}
  4. Opcionalmente, pruebe sus cambios usando Firebase Local Emulator Suite .
  5. Vuelva a implementar todas las funciones.

Establecer la versión de Python

Firebase SDK para Cloud Functions versiones 12.0.0 y superiores permiten la selección del tiempo de ejecución de Python. Configure la versión del tiempo de ejecución en firebase.json como se muestra:

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

Controlar el comportamiento de escalado

De forma predeterminada, Cloud Functions para Firebase escala la cantidad de instancias en ejecución según la cantidad de solicitudes entrantes, pudiendo reducirla a cero instancias en momentos de tráfico reducido. Sin embargo, si su aplicación requiere una latencia reducida y desea limitar la cantidad de inicios en frío, puede cambiar este comportamiento predeterminado especificando una cantidad mínima de instancias de contenedor que se mantendrán activas y listas para atender solicitudes.

De manera similar, puede establecer un número máximo para limitar el escalado de instancias en respuesta a solicitudes entrantes. Utilice esta configuración como una forma de controlar sus costos o limitar la cantidad de conexiones a un servicio de respaldo, como una base de datos.

Al utilizar esta configuración junto con la configuración de simultaneidad por instancia (nueva en la segunda generación), puede controlar y ajustar el comportamiento de escalado de sus funciones. La naturaleza de su aplicación y función determinará qué configuraciones son más rentables y darán como resultado el mejor rendimiento.

Para algunas aplicaciones con poco tráfico, lo óptimo es una opción de CPU más baja sin multiconcurrencia. Para otros donde los arranques en frío son un problema crítico, establecer una alta concurrencia y un mínimo de instancias significa que un conjunto de instancias siempre se mantiene activo para manejar grandes picos de tráfico.

Para aplicaciones de menor escala que reciben muy poco tráfico, establecer instancias máximas bajas con alta concurrencia significa que la aplicación puede manejar ráfagas de tráfico sin incurrir en costos excesivos. Sin embargo, tenga en cuenta que cuando el máximo de instancias se establece en un nivel demasiado bajo, es posible que las solicitudes se eliminen cuando se alcance el límite máximo.

Permitir solicitudes simultáneas

En Cloud Functions para Firebase (1.ª generación), cada instancia podía manejar una solicitud a la vez, por lo que el comportamiento de escalado se establecía solo con configuraciones de instancias mínima y máxima. Además de controlar la cantidad de instancias, en Cloud Functions para Firebase (segunda generación) puedes controlar la cantidad de solicitudes que cada instancia puede atender al mismo tiempo con la opción concurrency . El valor predeterminado para la simultaneidad es 80, pero puede establecerlo en cualquier número entero entre 1 y 1000.

Las funciones con configuraciones de concurrencia más altas pueden absorber picos de tráfico sin un arranque en frío porque es probable que cada instancia tenga cierto margen de maniobra. Si una instancia está configurada para manejar hasta 50 solicitudes simultáneas pero actualmente solo maneja 25, puede manejar un pico de 25 solicitudes adicionales sin necesidad de iniciar en frío una nueva instancia. Por el contrario, con una configuración de simultaneidad de solo 1, ese aumento en las solicitudes podría generar 25 inicios en frío.

Este escenario simplificado demuestra las posibles ganancias de eficiencia de la concurrencia. En realidad, escalar el comportamiento para optimizar la eficiencia y reducir los arranques en frío con concurrencia es más complejo. La simultaneidad en Cloud Functions para Firebase de segunda generación está impulsada por Cloud Run y ​​sigue las reglas de escalamiento automático de instancias de contenedor de Cloud Run.

Al experimentar con configuraciones de simultaneidad más altas en Cloud Functions para Firebase (segunda generación), tenga en cuenta lo siguiente:

  • Las configuraciones de simultaneidad más altas pueden requerir mayor CPU y RAM para un rendimiento óptimo hasta alcanzar un límite práctico. Una función que realiza un procesamiento pesado de imágenes o videos, por ejemplo, podría carecer de los recursos para manejar 1000 solicitudes simultáneas, incluso cuando sus configuraciones de CPU y RAM están maximizadas.
  • Dado que Cloud Functions para Firebase (segunda generación) funciona con Cloud Run, también puede consultar la guía de Google Cloud para optimizar la simultaneidad .
  • Asegúrese de probar exhaustivamente la multiconcurrencia en un entorno de prueba antes de cambiar a la multiconcurrencia en producción.

Mantenga un número mínimo de instancias calientes

Puede establecer un número mínimo de instancias para una función en el código fuente. Por ejemplo, esta función establece un mínimo de 5 instancias para mantenerse caliente:

Nodo.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
  }
);

Pitón

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

Aquí hay algunas cosas a considerar al establecer un valor mínimo de instancias:

  • Si Cloud Functions para Firebase escala tu aplicación por encima de tu configuración, experimentarás un inicio en frío para cada instancia que supere ese umbral.
  • Los arranques en frío tienen el efecto más grave en aplicaciones con mucho tráfico. Si su aplicación tiene un tráfico elevado y establece un valor lo suficientemente alto como para que los inicios en frío se reduzcan con cada aumento de tráfico, verá una latencia significativamente reducida. Para aplicaciones con tráfico constante, no es probable que los arranques en frío afecten gravemente al rendimiento.
  • Establecer instancias mínimas puede tener sentido para entornos de producción, pero normalmente debe evitarse en entornos de prueba. Para escalar a cero en su proyecto de prueba pero aún así reducir los arranques en frío en su proyecto de producción, puede establecer un valor de instancias mínimo en su configuración parametrizada:

    Nodo.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.`);
      }
    );
    

    Pitón

    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.")
    

Limitar el número máximo de instancias de una función

Puede establecer un valor para el número máximo de instancias en el código fuente de la función. Por ejemplo, esta función establece un límite de 100 instancias para no saturar una base de datos heredada hipotética:

Nodo.js

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

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

Pitón

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

Si una función HTTP se amplía hasta el límite máximo de instancias, las nuevas solicitudes se ponen en cola durante 30 segundos y luego se rechazan con un código de respuesta de 429 Too Many Requests si no hay ninguna instancia disponible para entonces.

Para obtener más información sobre las mejores prácticas para usar la configuración de instancias máximas, consulte estas prácticas recomendadas para configurar instancias máximas .

Establecer tiempo de espera y asignación de memoria

En algunos casos, sus funciones pueden tener requisitos especiales para un valor de tiempo de espera prolongado o una gran asignación de memoria. Puede configurar estos valores en la consola de Google Cloud o en el código fuente de la función (solo Firebase).

Para configurar la asignación de memoria y el tiempo de espera en el código fuente de las funciones, utilice las opciones globales de memoria y segundos de tiempo de espera para personalizar la máquina virtual que ejecuta sus funciones. Por ejemplo, esta función de Cloud Storage utiliza 1 GiB de memoria y se agota después de 300 segundos:

Nodo.js

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

Pitón

@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.

El valor máximo para los segundos de tiempo de espera es 540 o 9 minutos.

Para configurar la asignación de memoria y el tiempo de espera en la consola de Google Cloud:

  1. En la consola de Google Cloud, seleccione Funciones de nube para Firebase en el menú de la izquierda.
  2. Seleccione una función haciendo clic en su nombre en la lista de funciones.
  3. Haga clic en el icono Editar en el menú superior.
  4. Seleccione una asignación de memoria en el menú desplegable denominado Memoria asignada .
  5. Haga clic en Más para mostrar las opciones avanzadas e ingrese una cantidad de segundos en el cuadro de texto Tiempo de espera .
  6. Haga clic en Guardar para actualizar la función.

Anular los valores predeterminados de la CPU

Hasta 2 GB de memoria asignada, cada función en Cloud Functions para Firebase (segunda generación) tiene de forma predeterminada una CPU y luego aumenta a 2 CPU para 4 y 8 GB. Tenga en cuenta que esto es significativamente diferente del comportamiento predeterminado de la primera generación en formas que podrían generar costos ligeramente más altos para funciones con poca memoria, como se expresa en la siguiente tabla:

RAM asignada CPU predeterminada de la versión 1 (fraccional) CPU predeterminada de la versión 2 Aumento de precio por ms
128MB 1/12 1 10,5x
256MB 1/6 1 5,3x
512MB 1/3 1 2,7x
1GB 7/12 1 1,6x
2GB 1 1 1x
4 GB 2 2 1x
8GB 2 2 1x
16 GB n / A 4 n / A

Si prefiere el comportamiento de 1.ª generación para sus funciones de 2.ª generación, configure los valores predeterminados de 1.ª generación como una opción global:

Nodo.js

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

Pitón

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

Para funciones que requieren un uso intensivo de la CPU, la segunda generación brinda la flexibilidad de configurar CPU adicional. Puede aumentar la CPU por función como se muestra:

Nodo.js

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

Pitón

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