La semplicità di Cloud Functions ti consente di sviluppare rapidamente codice ed eseguirlo in un ambiente serverless. Su scala moderata, il costo dell'esecuzione delle funzioni è basso e l'ottimizzazione del codice potrebbe non sembrare una priorità elevata. Man mano che la distribuzione aumenta, tuttavia, l'ottimizzazione del codice diventa sempre più importante.
Questo documento descrive come ottimizzare il networking per le tue funzioni. Alcuni dei vantaggi dell'ottimizzazione della rete sono i seguenti:
- Riduci il tempo della CPU impiegato per stabilire nuove connessioni a ogni chiamata di funzione.
- Riduci la probabilità di esaurire la connessione o le quote DNS.
Mantenimento di connessioni persistenti
Questa sezione fornisce esempi su come mantenere connessioni persistenti in una funzione. In caso contrario, le quote di connessione potrebbero esaurirsi rapidamente.
In questa sezione vengono trattati i seguenti scenari:
- HTTP/S
- API di Google
Richieste HTTP/S
Il frammento di codice ottimizzato di seguito mostra come mantenere connessioni persistenti invece di creare una nuova connessione a ogni chiamata di funzione:
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(); });
Accesso alle API di Google
L'esempio seguente utilizza Cloud Pub/Sub , ma questo approccio funziona anche per altre librerie client, ad esempio Cloud Natural Language o Cloud Spanner . Si noti che i miglioramenti delle prestazioni possono dipendere dall'attuale implementazione di particolari librerie client.
La creazione di un oggetto client PubSub
comporta una connessione e due query DNS per chiamata. Per evitare connessioni e query DNS non necessarie, crea l'oggetto client PubSub
in ambito globale come mostrato nell'esempio seguente:
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'); } }); });
Test di carico della tua funzione
Per misurare quante connessioni esegue in media la tua funzione, distribuiscila semplicemente come funzione HTTP e utilizza un framework di test delle prestazioni per richiamarla a determinati QPS. Una possibile scelta è Artiglieria , che puoi richiamare con una sola riga:
$ artillery quick -d 300 -r 30 URL
Questo comando recupera l'URL specificato a 30 QPS per 300 secondi.
Dopo aver eseguito il test, controlla l'utilizzo della tua quota di connessione nella pagina della quota dell'API Cloud Functions in Cloud Console. Se l'utilizzo è costantemente intorno a 30 (o il suo multiplo), stai stabilendo una (o più) connessioni in ogni chiamata. Dopo aver ottimizzato il codice, dovresti vedere alcune (10-30) connessioni che si verificano solo all'inizio del test.
Puoi anche confrontare il costo della CPU prima e dopo l'ottimizzazione sul grafico della quota della CPU sulla stessa pagina.