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

提示与技巧

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

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

正确性

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

编写幂等函数

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

不启动后台活动

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

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

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

始终删除临时文件

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

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

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

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

工具

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

地方发展

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

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

使用 Sendgrid 发送邮件

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

表现

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

明智地使用依赖关系

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

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

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

无法保证为将来的调用保留 Cloud Functions 的状态。然而,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中了解有关优化性能的更多信息。