Google 致力于为黑人社区推动种族平等。查看具体举措

管理函数部署和运行时选项

您可以通过使用 Firebase CLI 命令或通过在函数源代码中设置运行时选项来部署、删除和修改函数。

部署函数

如需部署函数,请运行此 Firebase CLI 命令:

$ firebase deploy --only functions

默认情况下,Firebase CLI 会同时部署 index.js 内的所有函数。如果您的项目包含 5 个以上的函数,建议您使用 --only 标志并指定函数名称,以便仅部署您已修改的函数。以这种方式部署特定函数可加快部署流程,并有助于避免达到部署配额。例如:

$ firebase deploy --only functions:addMessage,functions:makeUppercase

部署大量函数时,可能会超出标准配额,并收到 HTTP 429 或 500 错误消息。如需解决此问题,请以 10 或更少数量为单位分批部署函数。

如需查看可用命令的完整列表,请参阅 Firebase CLI 参考文档

默认情况下,Firebase CLI 会在 functions/ 文件夹中查找源代码。您可以通过在 firebase.json 中添加以下行来指定另一文件夹:

"functions": {
  "source": "another-folder"
}

删除函数

您可以通过以下方式删除以前部署的函数:

  • 在 Firebase CLI 中使用 functions:delete 显式删除
  • 在 Firebase 控制台中使用函数列表中的上下文菜单显式删除
  • 在部署前通过从 index.js 中移除函数隐式删除。

所有删除操作都会提示您确认是否从生产环境中移除函数。

Firebase CLI 中的显式函数删除操作支持多个参数以及函数组,并允许您指定在特定区域中运行的函数。 此外,您还可以覆盖确认提示。

# Delete all functions that match the specified name in all regions.
$ firebase functions:delete myFunction

# Delete a specified function running in a specific region.
$ firebase functions:delete myFunction --region us-east-1

# Delete more than one function
$ firebase functions:delete myFunction myOtherFunction

# Delete a specified functions group.
$ firebase functions:delete groupA

# Bypass the confirmation prompt.
$ firebase functions:delete myFunction --force

对于隐式函数删除,firebase deploy 会解析 index.js 并从生产环境中移除已从文件中移除的任何函数。

修改函数的名称、区域或触发器

如要更改正在处理生产流量的函数的名称、区域或触发器,请按本部分中的步骤操作,以避免在修改期间丢失事件。在执行这些步骤之前,请先确保您的函数为幂等函数,因为在更改期间,函数的新版本和旧版本均会处于运行状态。

重命名函数

要重命名函数,请在 index.js 中创建函数改名后的新版本,然后分别运行两个部署命令。第一个命令部署改名后的函数,而第二个命令则移除以前部署的版本。例如,如果您要将名为 webhook 的函数更名为 webhookNew,请按以下方式修改代码:

// before
const functions = require('firebase-functions');

exports.webhook = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

// after
const functions = require('firebase-functions');

exports.webhookNew = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

然后运行以下命令,以部署新函数:

# Deploy new function called webhookNew
$ firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both webhookNew and webhook are running

# Delete webhook
$ firebase functions:delete webhook

更改函数的一个或多个区域

要更改正在处理生产流量的函数的指定区域,您可以按顺序执行以下步骤,以防止丢失事件:

  1. 重命名该函数,并根据需要更改其一个或多个区域。
  2. 部署重命名的函数,这样就会暂时在两组区域中运行相同的代码。
  3. 删除先前的函数。

例如,如果您有一个名为 webhook 的函数当前位于 us-central1 的默认函数区域,您希望将其迁移到 asia-northeast1,则需要先修改源代码重命名该函数并修改区域。

// before
const functions = require('firebase-functions');

exports.webhook = functions
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

// after
const functions = require('firebase-functions');

exports.webhookAsia = functions
    .region('asia-northeast1')
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

然后运行以下命令部署函数:

$ firebase deploy --only functions:webhookAsia

现在有两个相同的函数在运行:webhookus-central1 中运行,webhookAsiaasia-northeast1 中运行。

然后,删除 webhook

$ firebase functions:delete webhook

现在只有一个函数 webhookAsia,它在 asia-northeast1 中运行。

更改函数的触发器类型

当您的 Cloud Functions for Firebase 部署工作开展一段时间后,您可能会出于各种原因而需要更改函数的触发器类型。例如,您可能希望:

  • 从旧版存储 onChange 事件更改为 onFinalizeonDeleteonArchiveonMetadataUpdate。(如需了解这方面的详情,请参阅 Beta 版到 v1 或 v2 升级指南)。
  • 更改 Firebase Realtime Database 或 Cloud Firestore 事件的类型,例如,将宽泛的onWrite 事件更改为细化的 onCreate 事件。

仅凭更改源代码和运行 firebase deploy 无法更改函数的事件类型。为避免错误,请按以下程序更改函数的触发器类型:

  1. 修改源代码,以加入具备所需触发器类型的新函数。
  2. 部署该函数,这样暂时会同时运行旧函数和新函数。
  3. 利用 Firebase CLI 从生产环境中以显式方法删除旧函数。

例如,如果您有一个函数 objectChanged 具有旧版 onChange 事件类型,而您希望将其更改为 onFinalize,请先重命名该函数,然后对其进行修改为具有 onFinalize 事件类型。

// before
const functions = require('firebase-functions');

exports.objectChanged = functions.storage.object().onChange((object) => {
    return console.log('File name is: ', object.name);
});

// after
const functions = require('firebase-functions');

exports.objectFinalized = functions.storage.object().onFinalize((object) => {
    return console.log('File name is: ', object.name);
});

然后运行以下命令,以便先创建新函数,然后再删除旧函数:

# Create new function objectFinalized
$ firebase deploy --only functions:objectFinalized

# Wait until deployment is done; now both objectChanged and objectFinalized are running

# Delete objectChanged
$ firebase functions:delete objectChanged

设置运行时选项

Cloud Functions for Firebase 允许用户选择运行时选项,例如 Node.js 运行时版本、各函数的超时、内存分配以及函数实例数量上下限。

设置 Node.js 版本

Firebase SDK for Cloud Functions 2.0.0 及更高版本支持一系列 Node.js 运行时。 您可以选择仅在下面其中一个受支持的 Node.js 版本所对应的运行时环境中运行一个项目中的所有函数:

  • Node.js 14
  • Node.js 12
  • Node.js 10
  • Node.js 8(从 2020 年 6 月 8 日起弃用) 自 2020 年 12 月 15 日起,您已无法在 Firebase CLI 中将函数部署到 Node.js 8 运行时。已部署的函数会在将来某个时刻停止执行;如果您已将函数部署到 Node.js 8 运行时,我们建议您升级到 Node.js 14 运行时

要设置 Node.js 版本,请执行以下操作:

在初始化期间在 functions/ 目录中创建的 package.json 文件的 engines 字段中设置版本。 例如,要仅使用版本 14,请在 package.json 中修改此行:

  "engines": {"node": "14"}

engines 是必填字段;必须通过该字段指定一个受支持的 Node.js 版本,以便您部署和运行函数。目前,firebase init functions 将此字段设置为 14

升级 Node.js 运行时

如需升级 Node.js 运行时,请执行以下操作:

  1. 确保您的项目采用的是 Blaze 定价方案
  2. 确保您使用的是 Firebase CLI v8.6.0 或更高版本。
  3. 在初始化期间更改在 functions/ 目录中创建的 package.json 文件中的 engines 值。例如,如果您要从版本 10 升级到版本 14,则该条目应如下所示:"engines": {"node": "14"}
  4. (可选)使用 Firebase Local Emulator Suite 测试您的更改。
  5. 使用 Firebase CLI v8.1.0 或更高版本重新部署函数。

控制扩缩行为

默认情况下,Cloud Functions for Firebase 会根据传入请求数量扩缩运行的实例数量,当流量减少时可能会将实例数缩减为零。但是,如果您的应用要求缩短延迟时间,并且您希望限制冷启动次数,您可以通过指定保持备用状态已准备好处理请求的容器实例数下限来更改此默认行为。

同样,您也可以设置数量上限,以限制为应对传入请求而扩增的实例数。使用此设置可以控制您的费用或限制与备份服务(如数据库)的连接数。

减少冷启动次数

如需在源代码中为函数设置实例数下限,请使用 runWith 参数。此运行时选项接受符合 RuntimeOptions 接口的 JSON 对象(定义 minInstances 的值)。例如,此函数将保持备用状态的实例数下限设置为 5:

exports.getAutocompleteResponse = functions
    .runWith({
      // Keep 5 instances warm for this latency-critical function
      minInstances: 5,
    })
    .https.onCall((data, context) => {
      // Autocomplete a user's search term
    });

minInstances 设置值时,您需要考虑以下事项:

  • 如果 Cloud Functions for Firebase 将您的应用扩容到超过 minInstances 设置范围,超出该阈值以后的每个实例都会进行冷启动。
  • 冷启动对于有流量激增现象的应用的影响很严重。如果您的应用流量会激增,并且您将 minInstances 值设置得足够高,可以在每次流量增加时减少冷启动次数,现延迟时间将明显缩短。对于流量稳定的应用,冷启动不太可能严重影响性能。
  • 设置实例数下限可能适合生产环境,但在测试环境中通常应避免。如需在测试项目中缩减至零,但仍在生产项目中减少冷启动,您可以根据 FIREBASE_CONFIG 环境变量设置 minInstances

    // Get Firebase project id from `FIREBASE_CONFIG` environment variable
    const envProjectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
    
    exports.renderProfilePage = functions
        .runWith({
          // Keep 5 instances warm for this latency-critical function
          // in production only. Default to 0 for test projects.
          minInstances: envProjectId === "my-production-project" ? 5 : 0,
        })
        .https.onRequest((req, res) => {
          // render some html
        });
    

限制函数的实例数上限

如需在函数源代码中设置实例数上限,请使用 runWith 参数。此运行时选项接受符合 RuntimeOptions 接口的 JSON 对象(定义 maxInstances 的值)。例如,以下函数将实例数上限设置为 100,以避免假设的旧数据库超负荷:

exports.mirrorOrdersToLegacyDatabase = functions
    .runWith({
      // Legacy database only supports 100 simultaneous connections
      maxInstances: 100,
    })
    .firestore.document("orders/{orderId}")
    .onWrite((change, context) => {
      // Connect to legacy database
    });

如果 HTTP 函数扩容到 maxInstances 上限,则新请求将在队列中等候 30 秒;如果这段时间内仍没有可用的实例,则系统将拒绝此请求并返回响应代码 429 Too Many Requests

如需详细了解使用实例数上限设置的最佳做法,请查看这些使用 maxInstances 的最佳做法

设置超时时间和内存分配

在某些情况下,您的函数可能有特殊要求,需要具备较长的超时值或分配较多的内存。您可以在 Google Cloud Console 或函数源代码(仅限 Firebase)中设置这些值。

要在函数源代码中设置内存分配和超时,请使用 Firebase SDK for Cloud Functions 2.0.0 中引入的 runWith 参数。此运行时选项接受符合 RuntimeOptions 接口的 JSON 对象(定义 timeoutSecondsmemory 的值)。例如,以下存储函数使用 1GB 的内存,并会在 300 秒后超时:

exports.convertLargeFile = functions
    .runWith({
      // Ensure the function has enough memory and time
      // to process large files
      timeoutSeconds: 300,
      memory: "1GB",
    })
    .storage.object()
    .onFinalize((object) => {
      // Do some complicated things that take a lot of memory and time
    });

timeoutSeconds 的最大值为 540 或 9 分钟。memory 的有效值如下:

  • 128MB
  • 256MB
  • 512MB
  • 1GB
  • 2GB
  • 4GB
  • 8GB

要在 Google Cloud Console 中设置内存分配和超时,请执行以下操作:

  1. 在 Google Cloud Console 中,从左侧菜单中选择 Cloud Functions
  2. 点击函数列表中的名称,选择相应函数。
  3. 点击顶部菜单中的修改图标。
  4. 从名为分配的内存的下拉菜单中选择内存分配。
  5. 点击更多以显示高级选项,并在超时文本框中输入秒数。
  6. 点击保存以更新函数。