Check out what’s new from Firebase at Google I/O 2022. Learn more

管理函數部署和運行時選項

您可以使用 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 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 實時數據庫或 Cloud Firestore 事件更改為另一種類型,例如將通用onWrite事件更改為精細的onCreate事件。

僅通過更改源代碼並運行firebase deploy是無法更改函數的事件類型的。為避免錯誤,請通過以下過程更改函數的觸發器類型:

  1. 修改源代碼以包含具有所需觸發器類型的新函數。
  2. 部署函數,這會導致新舊函數都臨時運行。
  3. 使用 Firebase CLI 從生產環境中顯式刪除舊功能。

例如,如果您有一個具有傳統onChange事件類型的函數objectChanged ,並且您想將其更改為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 版本之一相對應的運行時環境中專門運行項目中的所有功能:

  • 節點.js 16
  • 節點.js 14
  • 節點.js 12
  • 節點.js 10
  • Node.js 8(2020 年 6 月 8 日棄用) 2020年 12 月 15 日,在 Firebase CLI 中禁用了向 Node.js 8 運行時部署函數。已部署函數的執行將在未來某個時間停止;如果您已經將函數部署到 Node.js 8 運行時,我們建議您升級到 Node.js 16 運行時

設置 Node.js 版本:

在初始化期間在您的functions/目錄中創建的package.json文件的engines字段中設置版本。例如,要僅使用版本 16,請在package.json中編輯此行:

  "engines": {"node": "16"}

engines字段是必需的;它必須指定受支持的 Node.js 版本之一,以便您部署和運行函數。目前firebase init functions將此字段設置為16

升級您的 Node.js 運行時

要升級您的 Node.js 運行時:

  1. 確保您的項目在Blaze 定價計劃中。
  2. 確保您使用的是 Firebase CLI v9.17.0 或更高版本。
  3. 更改初始化期間在您的functions/目錄中創建的package.json文件中的engines值。例如,如果您要從版本 10 升級到版本 16,則條目應如下所示: "engines": {"node": "16"}
  4. 或者,使用Firebase Local Emulator Suite測試您的更改。
  5. 使用 Firebase CLI v9.17.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 分鐘。授予函數的內存量對應於為函數分配的 CPU,如以下memory的有效值列表中所述:

  • 128MB — 200MHz
  • 256MB — 400MHz
  • 512MB — 800MHz
  • 1GB — 1.4 GHz
  • 2GB — 2.4 GHz
  • 4GB — 4.8 GHz
  • 8GB — 4.8 GHz

在 Google Cloud Console 中設置內存分配和超時:

  1. 在 Google Google Cloud Console 中,從左側菜單中選擇Cloud Functions
  2. 通過單擊函數列表中的名稱來選擇函數。
  3. 單擊頂部菜單中的編輯圖標。
  4. 從標記為已分配內存的下拉菜單中選擇內存分配
  5. 單擊更多以顯示高級選項,然後在超時文本框中輸入秒數。
  6. 單擊保存以更新函數。