获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

提示与技巧

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

本文档介绍了设计、实施、测试和部署 Cloud Functions 的最佳实践。

正确性

本节介绍设计和实施 Cloud Functions 的一般最佳实践。

编写幂等函数

即使您的函数被多次调用,它们也应该产生相同的结果。如果先前的调用在您的代码中途失败,这使您可以重试调用。有关详细信息,请参阅重试事件驱动函数

不启动后台活动

后台活动是您的函数终止后发生的任何事情。一旦函数返回或以其他方式发出完成信号,函数调用就会完成,例如通过调用 Node.js 事件驱动函数中的callback参数。优雅终止后运行的任何代码都无法访问 CPU,也不会取得任何进展。

此外,当在同一环境中执行后续调用时,您的后台活动会恢复,从而干扰新的调用。这可能会导致难以诊断的意外行为和错误。在函数终止后访问网络通常会导致连接被重置( ECONNRESET错误代码)。

后台活动通常可以在单个调用的日志中检测到,方法是查找在表示调用完成的行之后记录的任何内容。后台活动有时可能会更深地隐藏在代码中,尤其是在存在异步操作(例如回调或计时器)时。检查您的代码以确保在终止函数之前完成所有异步操作。

始终删除临时文件

临时目录中的本地磁盘存储是内存中的文件系统。您编写的文件会消耗函数可用的内存,并且有时会在调用之间持续存在。未能明确删除这些文件最终可能会导致内存不足错误和随后的冷启动。

您可以通过在 GCP Console的函数列表中选择单个函数并选择内存使用情况图来查看单个函数使用的内存。

不要尝试在临时目录之外写入,并确保使用平台/操作系统无关的方法来构建文件路径。

使用流水线处理较大的文件时,您可以减少内存需求。例如,您可以通过创建读取流、将其传递给基于流的进程并将输出流直接写入 Cloud Storage 来处理 Cloud Storage 上的文件。

工具

本节提供有关如何使用工具来实现、测试和与 Cloud Functions 交互的指南。

地方发展

函数部署需要一些时间,因此在本地测试函数的代码通常会更快。

Firebase 开发人员可以使用Firebase CLI Cloud Functions Emulator

使用 Sendgrid 发送电子邮件

Cloud Functions 不允许端口 25 上的出站连接,因此您无法与 SMTP 服务器建立非安全连接。发送电子邮件的推荐方法是使用SendGrid 。您可以在 Google Compute Engine的从实例发送电子邮件教程中找到其他发送电子邮件的选项。

表现

本节介绍优化性能的最佳实践。

明智地使用依赖项

因为函数是无状态的,所以执行环境通常是从头开始初始化的(在所谓的冷启动期间)。当发生冷启动时,将评估函数的全局上下文。

如果您的函数导入模块,则这些模块的加载时间可能会增加冷启动期间的调用延迟。您可以通过正确加载依赖项而不加载函数不使用的依赖项来减少此延迟以及部署函数所需的时间。

使用全局变量在未来的调用中重用对象

不能保证云函数的状态将被保留以供将来调用。但是,Cloud Functions 通常会回收先前调用的执行环境。如果您在全局范围内声明变量,则其值可以在后续调用中重用,而无需重新计算。

这样,您可以缓存在每个函数调用时重新创建可能代价高昂的对象。将此类对象从函数体移动到全局范围可能会导致显着的性能改进。以下示例为每个函数实例仅创建一次重对象,并在到达给定实例的所有函数调用中共享它:

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}`);
});

在全局范围内缓存网络连接、库引用和 API 客户端对象尤为重要。有关示例,请参阅优化网络

对全局变量进行延迟初始化

如果在全局范围内初始化变量,初始化代码将始终通过冷启动调用执行,从而增加函数的延迟。在某些情况下,如果在try / catch块中没有适当地处理被调用的服务,这会导致间歇性超时。如果某些对象未在所有代码路径中使用,请考虑按需延迟初始化它们:

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');
});

如果您在单个文件中定义多个函数,并且不同的函数使用不同的变量,这一点尤其重要。除非您使用延迟初始化,否则您可能会将资源浪费在已初始化但从未使用过的变量上。

通过设置最小实例数来减少冷启动

默认情况下,Cloud Functions 根据传入请求的数量扩展实例数量。您可以通过设置 Cloud Functions 必须准备好为请求提供服务的最小实例数来更改此默认行为。设置最小实例数可以减少应用程序的冷启动。如果您的应用程序对延迟敏感,我们建议设置最小实例数。

有关这些运行时选项的更多信息,请参阅控制缩放行为

其他资源

在“Google Cloud Performance Atlas”视频Cloud Functions Cold Boot Time中了解有关优化性能的更多信息。