Cloud Functions 的简单性让您可以快速开发代码并在无服务器环境中运行它。在中等规模下,运行函数的成本很低,优化代码似乎不是一个高优先级。然而,随着部署规模的扩大,优化代码变得越来越重要。
本文档描述了如何为您的函数优化网络。优化网络的一些好处如下:
- 减少在每次函数调用时建立新连接所花费的 CPU 时间。
- 降低用完连接或 DNS配额的可能性。
维护持久连接
本节举例说明如何在函数中维护持久连接。如果不这样做,可能会导致连接配额快速耗尽。
本节涵盖以下场景:
- HTTP/S
- 谷歌API
HTTP/S 请求
下面优化的代码片段展示了如何维护持久连接而不是在每次函数调用时创建新连接:
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(); });
访问谷歌 API
下面的示例使用Cloud Pub/Sub ,但这种方法也适用于其他客户端库,例如Cloud Natural Language或Cloud Spanner 。请注意,性能改进可能取决于特定客户端库的当前实现。
创建PubSub
客户端对象会导致每次调用一个连接和两个 DNS 查询。为避免不必要的连接和 DNS 查询,请在全局范围内创建PubSub
客户端对象,如下例所示:
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'); } }); });
负载测试你的功能
要衡量您的函数平均执行多少个连接,只需将其部署为 HTTP 函数并使用性能测试框架以特定 QPS 调用它。一种可能的选择是Artillery ,您可以用一行调用它:
$ artillery quick -d 300 -r 30 URL
此命令以 30 QPS 的速度获取给定的 URL 300 秒。
执行测试后,在 Cloud Console 的Cloud Functions API 配额页面检查您的连接配额使用情况。如果使用率一直在 30(或其倍数)左右,则您在每次调用中都建立了一个(或多个)连接。优化代码后,您应该会看到仅在测试开始时出现几个 (10-30) 个连接。
您还可以在同一页面的 CPU 配额图上比较优化前后的 CPU 成本。