管理功能


您可以使用 Firebase CLI 命令或透過在函數原始碼中設定執行時間選項來部署、刪除和修改函數。

部署功能

若要部署功能,請執行下列 Firebase CLI 命令:

firebase deploy --only functions

預設情況下,Firebase CLI 會同時部署來源中的所有功能。如果您的專案包含超過 5 個函數,我們建議您使用特定函數名稱的--only標誌來僅部署您已編輯的函數。以這種方式部署特定功能可以加快部署流程,並幫助您避免遇到部署配額。例如:

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

當部署大量函數時,您可能會超出標準配額並收到 HTTP 429 或 500 錯誤訊息。若要解決此問題,請按 10 個或更少的群組部署功能。

有關可用命令的完整列表,請參閱Firebase CLI 參考

預設情況下,Firebase CLI 在functions/資料夾中尋找原始程式碼。如果您願意,您可以在程式碼庫或多組檔案中組織函數

刪除功能

您可以透過以下方式刪除先前部署的功能:

  • 在 Firebase CLI 中明確使用functions:delete
  • 明確Google Cloud 控制台中。
  • 透過在部署之前從來源中刪除該函數來隱式實現。

所有刪除操作都會在從生產中刪除該功能之前提示您確認。

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會解析您的原始程式碼並從生產中刪除已從檔案中刪除的任何函數。

修改函數的名稱、區域或觸發器

如果您要重新命名或變更處理生產流量的函數的區域或觸發器,請按照本節中的步驟操作,以避免在修改期間遺失事件。在執行這些步驟之前,首先確保您的函數是冪等的,因為在更改期間函數的新版本和舊版本將同時運行。

重新命名函數

若要重新命名函數,請在來源中建立該函數的新重命名版本,然後執行兩個單獨的部署命令。第一個指令部署新命名的函數,第二個指令刪除先前部署的版本。例如,如果您想要重新命名一個 HTTP 觸發的 Webhook,請如下修改程式碼:

Node.js

// before
const {onRequest}  = require('firebase-functions/v2/https');

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

// after
const {onRequest}  = require('firebase-functions/v2/https');

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

Python

# before
from firebase_functions import https_fn

@https_fn.on_request()
def webhook(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

# after
from firebase_functions import https_fn

@https_fn.on_request()
def webhook_new(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response("Hello world!")

然後運行以下命令來部署新功能:

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

# Wait until deployment is done; now both functions are running

# Delete webhook
firebase functions:delete webhook

更改函數的一個或多個區域

如果您要變更處理生產流量的函數的指定區域,則可以透過依序執行下列步驟來防止事件遺失:

  1. 重新命名函數,並根據需要更改其一個或多個區域。
  2. 部署重命名的函數,這會導致在兩組區域中暫時執行相同的程式碼。
  3. 刪除之前的功能。

例如,如果您有一個 Cloud Firestore 觸發的函數,目前位於us-central1的預設函數區域中,並且您想要將其遷移到asia-northeast1 ,則需要先修改原始程式碼以重新命名該函數並修改該區域。

Node.js

// before
exports.firestoreTrigger = onDocumentCreated(
  "my-collection/{docId}",
  (event) => {},
);

// after
exports.firestoreTriggerAsia = onDocumentCreated(
  {
    document: "my-collection/{docId}",
    region: "asia-northeast1",
  },
  (event) => {},
);

更新後的程式碼應指定正確的事件篩選器(在本例中為document )以及區域。有關更多信息,請參閱Cloud Functions 位置

Python

# Before
@firestore_fn.on_document_created("my-collection/{docId}")
def firestore_trigger(event):
    pass

# After
@firestore_fn.on_document_created("my-collection/{docId}",
                                  region="asia-northeast1")
def firestore_trigger_asia(event):
    pass

然後透過運行進行部署:

firebase deploy --only functions:firestoreTriggerAsia

現在有兩個相同的函數正在運行: firestoreTriggerus-central1中運行, firestoreTriggerAsiaasia-northeast1中運行。

然後,刪除firestoreTrigger

firebase functions:delete firestoreTrigger

現在只有一個函數 - firestoreTriggerAsia ,它在asia-northeast1中運行。

更改函數的觸發類型

隨著時間的推移,當您開發 Cloud Functions for Firebase 部署時,您可能會因各種原因需要變更函數的觸發器類型。例如,您可能想要從一種類型的 Firebase 即時資料庫或 Cloud Firestore 事件變更為另一種類型。

僅透過更改原始程式碼並運行firebase deploy來更改函數的事件類型是不可能的。為了避免錯誤,請透過下列程序變更函數的觸發器類型:

  1. 修改原始程式碼以包含具有所需觸發類型的新函數。
  2. 部署該函數,這會導致臨時運行舊函數和新函數。
  3. 使用 Firebase CLI 從生產中明確刪除舊函數。

例如,如果您有一個在刪除物件時觸發的函數,但隨後啟用了物件版本控制並希望訂閱存檔事件,請先重新命名該函數並對其進行編輯以具有新的觸發器類型。

Node.js

// before
const {onObjectDeleted} = require("firebase-functions/v2/storage");

exports.objectDeleted = onObjectDeleted((event) => {
    // ...
});

// after
const {onObjectArchived} = require("firebase-functions/v2/storage");

exports.objectArchived = onObjectArchived((event) => {
    // ...
});

Python

# before
from firebase_functions import storage_fn

@storage_fn.on_object_deleted()
def object_deleted(event):
  # ...

# after 
from firebase_functions import storage_fn

@storage_fn.on_object_archived()
def object_archived(event):
  # ...

然後執行以下命令先建立新函數,然後再刪除舊函數:

# Create new function objectArchived
firebase deploy --only functions:objectArchived

# Wait until deployment is done; now both objectDeleted and objectArchived are running

# Delete objectDeleted
firebase functions:delete objectDeleted

設定運行時選項

Cloud Functions for Firebase 可讓您選擇執行時間選項,例如 Node.js 運行時版本和每個函數逾時、記憶體分配以及最小/最大函數實例。

作為最佳實踐,這些選項(Node.js 版本除外)應在函數程式碼內的配置物件上設定。此RuntimeOptions物件是函數執行階段選項的真實來源,並將覆寫透過任何其他方法(例如透過 Google Cloud 控制台或 gcloud CLI)設定的選項。

如果您的開發工作流程涉及透過 Google Cloud 控制台或 gcloud CLI 手動設定執行時間選項,且您希望在每次部署時覆寫這些值,請將preserveExternalChanges選項設為true 。將此選項設為true時,Firebase 會將程式碼中設定的執行時間選項與目前部署的函數版本的設定合併,優先順序如下:

  1. 選項在功能代碼中設定:覆蓋外部變更。
  2. 選項在功能代碼中設定為RESET_VALUE :使用預設值覆寫外部變更。
  3. 選項不在函數程式碼中設置,但在目前部署的函數中設定:使用已部署函數中指定的選項。

在大多數情況下,不建議使用preserveExternalChanges: true選項,因為您的程式碼將不再是函數執行時間選項的完整來源。如果您確實使用它,請檢查 Google Cloud 控制台或使用 gcloud CLI 查看函數的完整配置。

設定 Node.js 版本

適用於 Cloud Functions 的 Firebase SDK 允許選擇 Node.js 執行時期。您可以選擇在與下列受支援的 Node.js 版本之一對應的執行階段環境上專門執行專案中的所有函數:

  • Node.js 20 (預覽版)
  • Node.js 18
  • Node.js 16
  • Node.js 14

設定 Node.js 版本:

您可以在初始化期間在functions/目錄中建立的package.json檔案的engines欄位中設定版本。例如,若要僅使用版本 18,請在package.json中編輯以下行:

  "engines": {"node": "18"}

如果您使用 Yarn 套件管理器或對engines欄位有其他特定要求,則可以在firebase.json中設定 Firebase SDK for Cloud Functions 的執行時間:

  {
    "functions": {
      "runtime": "nodejs18" // or nodejs14, nodejs16 or nodejs20
    }
  }

CLI 優先使用firebase.json中設定的值,而不是您在package.json中單獨設定的任何值或範圍。

升級您的 Node.js 運行時

要升級 Node.js 執行時期:

  1. 確保您的項目在Blaze 定價計劃中。
  2. 確保您使用的是 Firebase CLI v11.18.0 或更高版本。
  3. 變更初始化期間在functions/目錄中建立的package.json檔案中的engines值。例如,如果您要從版本 16 升級到版本 18,則條目應如下所示: "engines": {"node": "18"}
  4. (可選)使用Firebase Local Emulator Suite測試您的變更。
  5. 重新部署所有功能。

設定Python版本

Firebase SDK for Cloud Functions 版本 12.0.0 及更高版本允許選擇 Python 執行時間。在firebase.json中設定運行時版本,如下所示:

  {
    "functions": {
      "runtime": "python310" // or python311
    }
  }

控制縮放行為

預設情況下,Cloud Functions for Firebase 會根據傳入請求的數量擴展正在執行的實例數量,在流量減少時可能會縮減至零實例。但是,如果您的應用程式需要減少延遲,並且您想要限製冷啟動的次數,則可以透過指定要保持溫暖並準備好服務請求的最小容器執行個體數量來變更此預設行為。

同樣,您可以設定最大數量來限制實例回應傳入請求的擴充。使用此設定來控製成本或限制與支援服務(例如資料庫)的連線數量。

將這些設定與每個實例的並發設定(第二代中的新增功能)結合使用,您可以控制和調整函數的擴充行為。您的應用程式和功能的性質將決定哪些設定最具成本效益,並將帶來最佳效能。

對於某些流量較低的應用程序,不使用多重同時的較低 CPU 選項是最佳選擇。對於其他冷啟動是關鍵問題的人來說,設定高並發和最少實例意味著一組實例始終保持溫暖以處理流量的大峰值。

對於接收流量很少的小型應用程序,設定較低的最大實例數和高並發意味著該應用程式可以處理突發流量,而不會產生過多的成本。但是,請記住,如果最大實例數設定得太低,則在達到上限時請求可能會被丟棄。

允許並發請求

在 Cloud Functions for Firebase(第一代)中,每個實例一次只能處理一個請求,因此僅使用最小和最大實例設定來設定擴充行為。除了控制執行個體數量之外,在 Cloud Functions for Firebase(第 2 代)中,您還可以使用concurrency選項來控制每個執行個體可以同時處理的請求數量。並發數的預設值為 80,但您可以將其設定為 1 到 1000 之間的任何整數。

具有較高並發設定的函數可以吸收流量峰值而無需冷啟動,因為每個實例可能都有一些空間。如果實例配置為處理最多 50 個並發請求,但目前僅處理 25 個,則它可以處理 25 個額外請求的峰值,而無需冷啟動新實例。相較之下,如果並發設定僅為 1,請求激增可能會導致 25 次冷啟動。

這個簡化的場景展示了並發的潛在效率提升。實際上,透過擴展來優化效率並減少並發冷啟動的行為更為複雜。 Cloud Functions for Firebase 第二代中的並發性由 Cloud Run 提供支持,並遵循 Cloud Run 的容器執行個體自動擴充規則。

在 Cloud Functions for Firebase(第 2 代)中嘗試更高的同時設定時,請記住以下幾點:

  • 較高的並發設定可能需要更高的 CPU 和 RAM 才能達到最佳效能,直到達到實際限制。例如,執行大量映像或視訊處理的函數可能缺乏處理 1000 個並發請求的資源,即使其 CPU 和 RAM 設定最大化也是如此。
  • 由於 Cloud Functions for Firebase(第二代)由 Cloud Run 提供支持,因此您也可以參考 Google Cloud優化並發指南。
  • 在生產中切換到多重並發之前,請確保在測試環境中徹底測試多重並發。

保持最少數量的實例溫暖

您可以在原始程式碼中設定函數的最小實例數。例如,此函數設定至少 5 個實例來保溫:

Node.js

const { onCall } = require("firebase-functions/v2/https");

exports.getAutocompleteResponse = onCall(
  {
    // Keep 5 instances warm for this latency-critical function
    minInstances: 5,
  },
  (event) => {
    // Autocomplete user’s search term
  }
);

Python

@https_fn.on_call(min_instances=5)
def get_autocomplete_response(event: https_fn.CallableRequest) -> https_fn.Response:

設定最小實例值時需要考慮以下事項:

  • 如果 Cloud Functions for Firebase 將您的應用程式擴展至高於您的設置,則對於高於該閾值的每個實例,您都會遇到冷啟動。
  • 冷啟動對流量高峰的應用程式影響最嚴重。如果您的應用程式流量激增,並且您將值設定得足夠高,以便每次流量增加時都會減少冷啟動,那麼您將看到延遲顯著減少。對於流量恆定的應用程序,冷啟動不太可能嚴重影響效能。
  • 設定最小實例對於生產環境有意義,但在測試環境中通常應避免。若要在測試專案中擴展到零,但仍減少生產專案中的冷啟動,您可以在參數化配置中設定最小實例值:

    Node.js

    const functions = require('firebase-functions');
    const { defineInt, defineString } = require('firebase-functions/params');
    
    // Define some parameters
    const minInstancesConfig = defineInt('HELLO_WORLD_MININSTANCES');
    const welcomeMessage = defineString('WELCOME_MESSAGE');
    
    // To use configured parameters inside the config for a function, provide them 
    // directly. To use them at runtime, call .value() on them.
    export const helloWorld = functions.runWith({ minInstances: minInstancesConfig}).https.onRequest(
      (req, res) => {
        res.send(`${welcomeMessage.value()}! I am a function.`);
      }
    );
    

    Python

    MIN_INSTANCES = params.IntParam("HELLO_WORLD_MININSTANCES")
    WELCOME_MESSAGE = params.StringParam("WELCOME_MESSAGE")
    
    @https_fn.on_request(min_instances=MIN_INSTANCES.value())
    def get_autocomplete_response(event: https_fn.Request) -> https_fn.Response:
        return https_fn.Response(f"{WELCOME_MESSAGE.value()} I'm a function.")
    

限制函數的最大實例數

您可以在函數原始碼中設定最大實例數的值。例如,此函數設定 100 個實例的限制,以免壓垮假設的遺留資料庫:

Node.js

const { onMessagePublished } = require("firebase-functions/v2/pubsub");

exports.mirrorevents = onMessagePublished(
  { topic: "topic-name", maxInstances: 100 },
  (event) => {
    // Connect to legacy database
  }
);

Python

@pubsub_fn.on_message_published(topic="topic-name", max_instances=100)
def mirrorevents(event: pubsub_fn.CloudEvent):
#  Connect to legacy database

如果 HTTP 函數擴展到最大實例數限制,則新請求將排隊 30 秒,然後如果此時沒有可用實例,則拒絕並傳回回應代碼429 Too Many Requests

要了解有關使用最大實例數設定的最佳實踐的更多信息,請查看這些設定最大實例數的最佳實踐

設定超時和記憶體分配

在某些情況下,您的函數可能對長逾時值或大量記憶體分配有特殊要求。您可以在 Google Cloud 控制台或函數原始碼(僅限 Firebase)中設定這些值。

若要在函數原始碼中設定記憶體分配和逾時,請使用記憶體和逾時秒數的全域選項來自訂運行函數的虛擬機器。例如,此 Cloud Storage 函數使用 1GiB 記憶體並在 300 秒後逾時:

Node.js

exports.convertLargeFile = onObjectFinalized({
  timeoutSeconds: 300,
  memory: "1GiB",
}, (event) => {
  // Do some complicated things that take a lot of memory and time
});

Python

@storage_fn.on_object_finalized(timeout_sec=300, memory=options.MemoryOption.GB_1)
def convert_large_file(event: storage_fn.CloudEvent):
# Do some complicated things that take a lot of memory and time.

超時秒數的最大值為540或 9 分鐘。

若要在 Google Cloud 控制台中設定記憶體分配和逾時,請執行以下操作:

  1. 在 Google Cloud 控制台中,從左側選單中選擇Cloud Functions for Firebase
  2. 透過在函數清單中點選函數名稱來選擇函數。
  3. 點擊頂部選單中的編輯圖示。
  4. 從標示「已分配記憶體」的下拉式選單中選擇記憶體分配。
  5. 按一下「更多」以顯示進階選項,然後在「逾時」文字方塊中輸入秒數。
  6. 點擊“儲存”以更新函數。

覆蓋CPU預設值

Cloud Functions for Firebase(第 2 代)中的每個函數最多分配 2GB 內存,預設為 1 個 CPU,然後增加到 2 個 CPU(4 GB 和 8 GB)。請注意,這與第一代預設行為顯著不同,可能導致低記憶體函數的成本稍高,如下表所示:

記憶體分配版本 1 預設 CPU(部分)版本 2 預設 CPU每毫秒價格上漲
128MB 1/12 1 10.5倍
256MB 1/6 1 5.3倍
512MB 1/3 1 2.7倍
1GB 7/12 1 1.6倍
2GB 1 1 1x
4GB 2 2 1x
8GB 2 2 1x
16 GB不適用4不適用

如果您喜歡第二代函數的第一代行為,請將第一代預設值設為全域選項:

Node.js

// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcf_gen1' });

Python

# Use 1st gen behavior
set_global_options(cpu="gcf_gen1")

對於 CPU 密集型功能,第二代提供了配置額外 CPU 的靈活性。您可以依功能提升 CPU,如下所示:

Node.js

// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
  // computer vision goes here
});

Python

# Boost CPU in a function:
@storage_fn.on_object_finalized(cpu=2)
def analyze_image(event: storage_fn.CloudEvent):
# computer vision goes here