Prostota Cloud Functions pozwala szybko tworzyć kod i uruchamiać go w środowisku bezserwerowym. W umiarkowanej skali koszt uruchamiania funkcji jest niski, a optymalizacja kodu może nie wydawać się priorytetem. Jednak wraz ze wzrostem skali wdrożenia optymalizacja kodu staje się coraz ważniejsza.
W tym dokumencie opisano, jak zoptymalizować sieć dla swoich funkcji. Oto niektóre korzyści płynące z optymalizacji sieci:
- Skróć czas procesora poświęcany na nawiązywanie nowych połączeń przy każdym wywołaniu funkcji.
- Zmniejsz prawdopodobieństwo wyczerpania limitów połączeń lub DNS.
Utrzymywanie trwałych połączeń
Ta sekcja zawiera przykłady utrzymywania trwałych połączeń w funkcji. Niezastosowanie się do tego zalecenia może spowodować szybkie wyczerpanie limitów połączeń.
W tej sekcji omówiono następujące scenariusze:
- HTTP/S
- API Google
Żądania HTTP/S
Poniższy zoptymalizowany fragment kodu pokazuje, jak utrzymywać trwałe połączenia zamiast tworzyć nowe połączenie przy każdym wywołaniu funkcji:
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(); });
Dostęp do interfejsów API Google
Poniższy przykład wykorzystuje Cloud Pub/Sub , ale to podejście działa również w przypadku innych bibliotek klienckich, na przykład Cloud Natural Language lub Cloud Spanner . Należy pamiętać, że poprawa wydajności może zależeć od bieżącej implementacji poszczególnych bibliotek klienckich.
Utworzenie obiektu klienta PubSub
skutkuje utworzeniem jednego połączenia i dwóch zapytań DNS na wywołanie. Aby uniknąć niepotrzebnych połączeń i zapytań DNS, utwórz obiekt klienta PubSub
w zakresie globalnym, jak pokazano w przykładzie poniżej:
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'); } }); });
Testowanie obciążenia Twojej funkcji
Aby zmierzyć, ile średnio połączeń wykonuje Twoja funkcja, po prostu wdróż ją jako funkcję HTTP i użyj frameworka do testowania wydajności, aby wywołać ją w określonym QPS. Jednym z możliwych wyborów jest Artyleria , którą możesz wezwać za pomocą jednej linii:
$ artillery quick -d 300 -r 30 URL
To polecenie pobiera podany adres URL z szybkością 30 QPS przez 300 sekund.
Po przeprowadzeniu testu sprawdź wykorzystanie limitu połączenia na stronie limitów interfejsu Cloud Functions API w Cloud Console. Jeśli użycie stale wynosi około 30 (lub jego wielokrotność), ustanawiasz jedno (lub kilka) połączeń w każdym wywołaniu. Po zoptymalizowaniu kodu powinno pojawić się kilka (10-30) połączeń tylko na początku testu.
Możesz również porównać koszt procesora przed optymalizacją i po niej na wykresie przydziału procesora na tej samej stronie.