Optimizar las herramientas de redes

La simplicidad de Cloud Functions te permite programar código rápidamente y ejecutarlo en un entorno sin servidores. A una escala moderada, el costo de ejecutar funciones es bajo, y puedes considerar que optimizar tu código no es una prioridad importante. Sin embargo, a medida que tu implementación aumenta su escala, optimizar tu código se vuelve cada vez más relevante.

En este documento, se describe cómo optimizar las Herramientas de redes para tus funciones. Algunos de los beneficios de optimizar las Herramientas de redes son los siguientes:

  • Reduce el tiempo de CPU que se usa para establecer conexiones nuevas en cada llamada de función.
  • Reduce la probabilidad de agotar las cuotas de DNS o de conexión.

Mantén conexiones continuas

Esta sección muestra ejemplos sobre cómo mantener conexiones continuas en una función. No hacerlo puede causar que agotes tu cuota de conexión rápidamente.

En esta sección, se abordan los siguientes casos:

  • HTTP/S
  • API de Google

Solicitudes HTTP(S)

El fragmento de código optimizado de más abajo muestra cómo mantener la coherencia de las conexiones en lugar de crear una conexión nueva para cada invocación de función:

const http = require('http');
const functions = require('firebase-functions');

// Setting the `keepAlive` option to `true` keeps
// connections open between function invocations
const agent = new http.Agent({keepAlive: true});

exports.function = functions.https.onRequest((request, response) => {
    req = http.request({
        host: '',
        port: 80,
        path: '',
        method: 'GET',
        agent: agent, // Holds the connection open after the first invocation
    }, res => {
        let rawData = '';
        res.setEncoding('utf8');
        res.on('data', chunk => { rawData += chunk; });
        res.on('end', () => {
            response.status(200).send(`Data: ${rawData}`);
        });
    });
    req.on('error', e => {
        response.status(500).send(`Error: ${e.message}`);
    });
    req.end();
});

Acceso a las API de Google

En el siguiente ejemplo, se usa Cloud Pub/Sub, pero este enfoque también sirve para otras bibliotecas cliente, como Cloud Natural Language o Cloud Spanner. Ten en cuenta que las mejoras de rendimiento pueden depender de la implementación actual de algunas bibliotecas cliente en particular.

Si se crea un objeto de cliente de PubSub, se establece una conexión y se generan dos consultas de DNS por invocación. Para evitar consultas de DNS y conexiones innecesarias, crea el objeto de cliente de PubSub en alcance global, como se indica en el siguiente ejemplo:

const PubSub = require('@google-cloud/pubsub');
const functions = require('firebase-functions');
const pubsub = PubSub();

exports.function = functions.https.onRequest((req, res) => {
    const topic = pubsub.topic('');

    topic.publish('Test message', err => {
        if (err) {
            res.status(500).send(`Error publishing the message: ${err}`);
        } else {
            res.status(200).send('1 message published');
        }
    });
});

Prueba la carga de tu función

Para medir cuántas conexiones ejecuta en promedio tu función, solo debes implementarla como una función de HTTP y usar un marco de trabajo de prueba de rendimiento para invocarla con una cierta cantidad de QPS. Una opción posible es Artillery, que puedes invocar con una sola línea:

$ artillery quick -d 300 -r 30 URL

Con este comando, se recupera la URL dada a 30 QPS por 300 segundos.

Después de ejecutar la prueba, verifica el uso de tu cuota de conexión en la página de cuotas de la API de Cloud Functions en la consola de Cloud. Si el uso se mantiene alrededor de 30 (o sus múltiplos), estás estableciendo una (o varias) conexiones en cada invocación. Después de optimizar el código, deberías ver que se ejecutan unas pocas conexiones (entre 10 y 30) solo al comienzo de la prueba.

También puedes comparar el costo de CPU antes y después de la optimización en el gráfico de cuota de CPU, en la misma página.