Sugerencias

En este documento se describen las recomendaciones para diseñar, implementar y probar Cloud Functions.

Precisión

Esta sección describe las recomendaciones generales para diseñar y también implementar Cloud Functions.

Escribir funciones idempotentes

Tus funciones deben producir el mismo resultado, incluso si se llaman varias veces. Esto te permite volver a intentar una invocación si la anterior falla a mitad de camino en el código. Para obtener más información, consulta cómo volver a intentar ejecutar funciones en segundo plano.

Borra los archivos temporales siempre

El almacenamiento en el directorio temporal del disco local es un sistema de archivos en la memoria. Los archivos que escribes consumen memoria disponible en tu función y a veces persisten entre invocaciones. No borrar estos archivos explícitamente podría generar un error por falta de memoria y un posterior inicio en frío.

Para ver la memoria que usa una función individual, selecciónala en la lista de funciones de la Consola de API y elige el gráfico “Uso de memoria”.

No intentes escribir fuera del directorio temporal y asegúrate de usar métodos independientes de SO/plataforma para construir rutas de acceso.

Puedes usar la canalización para evitar las restricciones de tamaño en archivos temporales. Por ejemplo, para procesar un archivo en Cloud Storage, puedes crear un flujo de lectura, pasarlo a través de un proceso basado en el flujo y escribir el flujo saliente directamente en Cloud Storage.

Herramientas

Esta sección proporciona lineamientos sobre cómo usar herramientas para implementar, probar y también interactuar con Cloud Functions.

Desarrollo local

La implementación de funciones tarda un momento, por lo que suele ser más rápido probar el código de tu función de manera local con un corrector de compatibilidad.

Te recomendamos usar el Emulador de Cloud Functions para Node.js como corrector de compatibilidad.

Usa Sendgrid para enviar correos electrónicos

Cloud Functions no permite conexiones salientes en el puerto 25, por lo que no puedes establecer conexiones no seguras a un servidor SMTP. Para enviar correos electrónicos, se recomienda usar SendGrid. Puedes encontrar un ejemplo completo en el Instructivo de SendGrid. Otras opciones para enviar correos electrónicos se describen en el Documento de Google Compute Engine Cómo enviar correos electrónicos desde una instancia.

Rendimiento

Esta sección describe las recomendaciones para optimizar el rendimiento.

Usa las dependencias de manera inteligente

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

Si tus funciones importan módulos, el tiempo de carga de estos se agrega a la latencia de invocación durante un inicio en frío. Para reducir esta latencia y el tiempo que se requiere para implementar tu función, carga las dependencias correctamente y no cargues las dependencias que tu función no utiliza.

Usa variables globales para volver a usar objetos en invocaciones futuras

No se garantiza que el estado de una función de Cloud Functions se conserve para las invocaciones futuras. Sin embargo, Cloud Functions suele reciclar el entorno de ejecución de una invocación previa. Si declaras una variable en alcance global, su valor se puede volver a usar en invocaciones posteriores sin tener que volver a procesarse.

De esta manera, puedes almacenar objetos en la caché, ya que volver a crearlos en cada invocación de la función puede ser costoso. Mover estos objetos desde el cuerpo de la función al alcance global puede generar importantes mejoras en el rendimiento. El siguiente ejemplo crea un objeto pesado solo una vez por instancia de la función y lo comparte en todas las invocaciones de la función que alcanzan la instancia determinada:

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, la biblioteca, las referencias y los clientes de la API en alcance global. Consulta cómo optimizar las herramientas de redes para ver ejemplos.

Haz una inicialización diferida de las variables globales

Si inicializas variables en alcance global, el código de inicialización se ejecutará siempre a través de una invocación de inicio en frío, lo que aumenta la latencia de tu función. Si algunos objetos no se usan en todas las rutas del código, te recomendamos inicializarlos de forma diferida según demanda:

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 especialmente importante si defines varias funciones en un solo archivo y si varias funciones usan variables diferentes. A menos que uses la inicialización diferida, puedes perder recursos si inicializas variables que nunca se usan.

Recursos adicionales

Obtén más información sobre cómo optimizar el rendimiento en el video de “Atlas de rendimiento de Google Cloud”, Cloud Functions Cold Boot Time (Tiempo de inicio en frío de Cloud Functions).

Enviar comentarios sobre...

Si necesitas ayuda, visita nuestra página de asistencia.