Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Consejos y trucos

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Este documento describe las mejores prácticas para diseñar, implementar, probar y desplegar Cloud Functions.

Exactitud

Esta sección describe las mejores prácticas generales para diseñar e implementar Cloud Functions.

Escribir funciones idempotentes

Sus funciones deberían producir el mismo resultado incluso si se llaman varias veces. Esto le permite volver a intentar una invocación si la invocación anterior falla a la mitad del código. Para obtener más información, consulte reintentar funciones basadas en eventos .

No inicie actividades en segundo plano

La actividad en segundo plano es cualquier cosa que sucede después de que su función ha terminado. La invocación de una función finaliza una vez que la función regresa o indica que se completó, por ejemplo, llamando al argumento de callback de llamada en las funciones controladas por eventos de Node.js. Cualquier código que se ejecute después de una finalización correcta no podrá acceder a la CPU y no progresará.

Además, cuando se ejecuta una invocación posterior en el mismo entorno, se reanuda su actividad en segundo plano, lo que interfiere con la nueva invocación. Esto puede provocar un comportamiento inesperado y errores que son difíciles de diagnosticar. Acceder a la red después de que finaliza una función generalmente conduce a que se restablezcan las conexiones (código de error ECONNRESET ).

La actividad en segundo plano a menudo se puede detectar en registros de invocaciones individuales, al encontrar cualquier cosa que se registre después de la línea que dice que la invocación finalizó. A veces, la actividad en segundo plano puede ocultarse más profundamente en el código, especialmente cuando hay presentes operaciones asincrónicas, como devoluciones de llamada o temporizadores. Revise su código para asegurarse de que todas las operaciones asincrónicas finalicen antes de finalizar la función.

Eliminar siempre los archivos temporales

El almacenamiento en disco local en el directorio temporal es un sistema de archivos en memoria. Los archivos que escribe consumen memoria disponible para su función y, a veces, persisten entre invocaciones. Si no se eliminan explícitamente estos archivos, es posible que se produzca un error de falta de memoria y un inicio en frío posterior.

Puede ver la memoria utilizada por una función individual seleccionándola en la lista de funciones en GCP Console y eligiendo el gráfico de uso de memoria .

No intente escribir fuera del directorio temporal y asegúrese de utilizar métodos independientes de la plataforma o del sistema operativo para construir las rutas de los archivos.

Puede reducir los requisitos de memoria al procesar archivos más grandes mediante canalización. Por ejemplo, puede procesar un archivo en Cloud Storage creando un flujo de lectura, pasándolo a través de un proceso basado en flujo y escribiendo el flujo de salida directamente en Cloud Storage.

Instrumentos

Esta sección proporciona pautas sobre cómo usar herramientas para implementar, probar e interactuar con Cloud Functions.

desarrollo local

La implementación de funciones lleva un poco de tiempo, por lo que a menudo es más rápido probar el código de su función localmente.

Los desarrolladores de Firebase pueden usar Firebase CLI Cloud Functions Emulator .

Utilice Sendgrid para enviar correos electrónicos

Cloud Functions no permite conexiones salientes en el puerto 25, por lo que no puede realizar conexiones no seguras a un servidor SMTP. La forma recomendada de enviar correos electrónicos es usar SendGrid . Puede encontrar otras opciones para enviar correo electrónico en el tutorial Envío de correo electrónico desde una instancia para Google Compute Engine.

Actuación

Esta sección describe las mejores prácticas para optimizar el rendimiento.

Usa las dependencias sabiamente

Debido a que las funciones no tienen estado, el entorno de ejecución a menudo se inicializa desde cero (durante lo que se conoce como inicio en frío ). Cuando se produce un arranque en frío, se evalúa el contexto global de la función.

Si sus funciones importan módulos, el tiempo de carga de esos módulos puede aumentar la latencia de invocación durante un arranque en frío. Puede reducir esta latencia, así como el tiempo necesario para implementar su función, cargando las dependencias correctamente y no cargando las dependencias que su función no usa.

Use variables globales para reutilizar objetos en invocaciones futuras

No hay garantía de que el estado de una Cloud Function se conserve para invocaciones futuras. Sin embargo, Cloud Functions suele reciclar el entorno de ejecución de una invocación anterior. Si declara una variable en ámbito global, su valor se puede reutilizar en invocaciones posteriores sin tener que volver a calcular.

De esta manera, puede almacenar en caché objetos que pueden ser costosos de recrear en cada invocación de función. Mover dichos objetos del cuerpo de la función al alcance global puede generar mejoras significativas en el rendimiento. El siguiente ejemplo crea un objeto pesado solo una vez por instancia de función y lo comparte en todas las invocaciones de funciones que llegan a la instancia dada:

console.log('Global scope');
const perInstance = heavyComputation();
const functions = require('firebase-functions');

exports.function = functions.https.onRequest((req, res) => {
    console.log('Function invocation');
    const perFunction = lightweightComputation();

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

Es especialmente importante almacenar en caché las conexiones de red, las referencias de biblioteca y los objetos de cliente de API en el ámbito global. Consulte Optimización de redes para ver ejemplos.

Hacer inicialización perezosa de variables globales

Si inicializa variables en el ámbito global, el código de inicialización siempre se ejecutará a través de una invocación de inicio en frío, lo que aumenta la latencia de su función. En ciertos casos, esto provoca tiempos de espera intermitentes para los servicios que se llaman si no se manejan adecuadamente en un bloque try / catch . Si algunos objetos no se usan en todas las rutas de código, considere inicializarlos de forma perezosa a pedido:

const functions = require('firebase-functions');
let myCostlyVariable;

exports.function = functions.https.onRequest((req, res) => {
    doUsualWork();
    if(unlikelyCondition()){
        myCostlyVariable = myCostlyVariable || buildCostlyVariable();
    }
    res.status(200).send('OK');
});

Esto es particularmente importante si define varias funciones en un solo archivo y diferentes funciones usan diferentes variables. A menos que use la inicialización diferida, puede desperdiciar recursos en variables que se inicializan pero nunca se usan.

Reduzca los arranques en frío estableciendo un número mínimo de instancias

De forma predeterminada, Cloud Functions escala la cantidad de instancias según la cantidad de solicitudes entrantes. Puede cambiar este comportamiento predeterminado configurando una cantidad mínima de instancias que Cloud Functions debe mantener listas para atender solicitudes. Establecer un número mínimo de instancias reduce los inicios en frío de su aplicación. Recomendamos establecer una cantidad mínima de instancias si su aplicación es sensible a la latencia.

Consulte Controlar el comportamiento de escalado para obtener más información sobre estas opciones de tiempo de ejecución.

Recursos adicionales

Obtenga más información sobre cómo optimizar el rendimiento en el video "Google Cloud Performance Atlas" Cloud Functions Cold Boot Time .