您可以使用 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 {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");
});
然後運行以下命令來部署新功能:
# 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
更改一個或多個函數的區域
如果您要更改處理生產流量的函數的指定區域,則可以通過按順序執行以下步驟來防止事件丟失:
- 重命名函數,並根據需要更改其區域。
- 部署重命名的函數,這會導致在兩組區域中臨時運行相同的代碼。
- 刪除之前的功能。
例如,如果您有一個名為webhook
的函數當前位於us-central1
的默認函數區域,並且您想將其遷移到asia-northeast1
,則需要先修改源代碼以重命名該函數並修改區域.
// 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.webhookasia = onRequest({
region: 'asia-northeast1'
}, (req, res) => {
res.send("Hello");
});
然後通過運行部署:
$ firebase deploy --only functions:webhookAsia
現在有兩個相同的函數在運行: webhook
在us-central1
中運行, webhookasia
在asia-northeast1
中運行。
然後,刪除webhook
:
$ firebase functions:delete webhook
現在只有一個功能 - webhookasia
,它在asia-northeast1
中運行。
更改函數的觸發器類型
隨著時間的推移開發 Cloud Functions for Firebase 部署,您可能需要出於各種原因更改函數的觸發器類型。例如,您可能希望將一種類型的 Firebase 實時數據庫或 Cloud Firestore 事件更改為另一種類型,例如將通用的onWrite
事件更改為精細的onCreate
事件。
僅通過更改源代碼和運行firebase deploy
是不可能更改函數的事件類型的。為避免錯誤,請通過以下過程更改函數的觸發器類型:
- 修改源代碼以包含具有所需觸發器類型的新函數。
- 部署函數,這會導致臨時運行舊函數和新函數。
- 使用 Firebase CLI 從生產中明確刪除舊函數。
例如,如果您有一個函數objectchanged
具有遺留的onMetadataUpdated
事件類型,並且您想將其更改為onObjectFinalized
,請首先重命名該函數並將其編輯為具有onObjectFinalized
事件類型。
// before
const {onMetadataUpdated} = require('firebase-functions/v2/storage');
exports.objectchanged = onMetadataUpdated((event) => {
return console.log('File name is: ', event.data.name);
});
// after
const {onObjectFinalized} = require('firebase-functions/v2/storage');
exports.objectchanged = onObjectFinalized((event) => {
return console.log('File name is: ', event.data.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 版本除外)。此RuntimeOptions
對像是函數運行時選項的真實來源,並將覆蓋通過任何其他方法(例如通過 Google Cloud 控制台或 gcloud CLI)設置的選項。
如果您的開發工作流程涉及通過 Google Cloud 控制台或 gcloud CLI 手動設置運行時選項,並且您不希望在每次部署時覆蓋這些值,請將preserveExternalChanges
選項設置為true
。將此選項設置為true
後,Firebase 會將代碼中設置的運行時選項與當前部署的函數版本的設置合併,優先級如下:
- 選項在功能代碼中設置:覆蓋外部更改。
- 選項在函數代碼中設置為
RESET_VALUE
:使用默認值覆蓋外部更改。 - 選項未在函數代碼中設置,但在當前部署的函數中設置:使用已部署函數中指定的選項。
在大多數情況下,不建議使用preserveExternalChanges: true
選項,因為您的代碼將不再是函數運行時選項的完整真實來源。如果確實要使用它,請檢查 Google Cloud 控制台或使用 gcloud CLI 查看函數的完整配置。
設置 Node.js 版本
Firebase SDK for Cloud Functions(第 2 代)允許選擇 Node.js 運行時。您可以選擇在與這些受支持的 Node.js 版本之一相對應的運行時環境中專門運行項目中的所有功能:
- 節點 16
- 節點 14
設置 Node.js 版本:
在初始化期間在您的functions/
目錄中創建的package.json
文件中的engines
字段中設置版本。例如,要僅使用版本 16,請在package.json
中編輯此行:
"engines": {"node": "16"}
engines
字段是必需的;它必須指定受支持的 Node.js 版本之一,以便您部署和運行功能。目前firebase init functions
將此字段設置為16
。
升級您的 Node.js 運行時
要升級您的 Node.js 運行時:
- 確保您的項目在Blaze 定價計劃中。
- 確保您使用的是 Firebase CLI v9.17.0 或更高版本。
- 更改初始化期間在
functions/
目錄中創建的package.json
文件中的engines
值。例如,如果您要從版本 10 升級到版本 16,條目應如下所示:"engines": {"node": "16"}
- 使用 Firebase CLI v9.17.0 或更高版本重新部署函數。
控制縮放行為
默認情況下,Cloud Functions for Firebase 根據傳入請求的數量縮放正在運行的實例的數量,並可能在流量減少時縮減為零個實例。但是,如果您的應用程序需要減少延遲並且您想要限製冷啟動的次數,您可以通過指定最小數量的容器實例來保持溫暖並準備好為請求服務來更改此默認行為。
同樣,您可以設置最大數量來限制實例響應傳入請求的擴展。使用此設置來控製成本或限制與支持服務(例如數據庫)的連接數。
將這些設置與每個實例的並發設置(第二代中的新增功能)結合使用,您可以控制和調整函數的擴展行為。您的應用程序和功能的性質將決定哪些設置最具成本效益並將產生最佳性能。
對於一些低流量的應用程序,沒有多並發的較低 CPU 選項是最佳選擇。對於冷啟動是一個關鍵問題的其他人來說,設置高並發和最小實例意味著一組實例始終保持溫暖以處理流量的大峰值。
對於接收流量非常小的小型應用程序,設置較低的最大實例數和高並發意味著應用程序可以處理突發流量,而不會產生過多的成本。
允許並發請求
在 Cloud Functions for Firebase(第一代)中,每個實例一次可以處理一個請求,因此縮放行為僅通過minInstances
和maxInstances
設置來設置。除了控制實例數量外,在 Cloud Functions for Firebase(第 2 代)中,您還可以使用concurrency
選項控制每個實例可以同時服務的請求數量。並發的默認值為 80,但您可以將其設置為 1 到 1000 之間的任何整數。
具有較高並發設置的函數可以在不冷啟動的情況下吸收流量峰值,因為每個實例可能都有一些空間。如果一個實例配置為處理最多 50 個並發請求,但當前僅處理 25 個,則它可以處理 25 個額外請求的峰值,而無需新實例冷啟動。相比之下,如果並發設置僅為 1,那麼請求激增可能會導致 25 次冷啟動。
在 Cloud Functions for Firebase(第 2 代)中試驗更高的並發設置時,請記住以下幾點:
- 更高的並發設置可能需要更高的 CPU 和 RAM 才能獲得最佳性能,直到達到實際限制。例如,執行大量圖像或視頻處理的函數可能缺乏處理 1000 個並發請求的資源,即使其 CPU 和 RAM 設置已最大化。
- 由於 Cloud Functions for Firebase(第 2 代)由 Cloud Run 提供支持,您還可以參考谷歌云優化並髮指南。
- 在生產中切換到多並發之前,請確保在測試環境中徹底測試多並發。
減少冷啟動次數
要在源代碼中設置函數的最小實例數,請使用minInstances
選項。例如,此函數設置最少 5 個實例以保暖:
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
}
);
以下是為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 = onRequest( { // 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, }, (req, res) => { // render some html } );
限制函數的最大實例數
要在函數源代碼中設置最大實例數,請使用maxInstances
選項。例如,此函數設置 100 個實例的限制,以免淹沒假設的遺留數據庫:
const { onMessagePublished } = require("firebase-functions/v2/pubsub");
exports.mirrorevents = onMessagePublished(
{ topic: "topic-name", maxInstances: 100 },
(event) => {
// Connect to legacy database
}
);
如果 HTTP 函數擴展到maxInstances
限制,新請求將排隊 30 秒,然後在沒有可用實例的情況下被拒絕,響應代碼為429 Too Many Requests
。
要了解有關使用最大實例設置的最佳實踐的更多信息,請查看這些使用maxInstances
最佳實踐。
設置超時和內存分配
在某些情況下,您的函數可能對長超時值或大量內存分配有特殊要求。您可以在 Google Cloud Console 或函數源代碼(僅限 Firebase)中設置這些值。
要在函數源代碼中設置內存分配和超時,請使用GlobalOptions.memory
和GlobalOptions.timeoutSeconds
自定義運行函數的虛擬機。例如,此 Cloud Storage 函數使用 1GiB 內存並在 300 秒後超時:
exports.convertLargeFile = onObjectFinalized({
timeoutSeconds: 300,
memory: "1GiB",
}, (event) => {
// Do some complicated things that take a lot of memory and time
});
timeoutSeconds
的最大值為540
或 9 分鐘。
要在 Google Cloud Console 中設置內存分配和超時:
- 在 Google Cloud Console 中,從左側菜單中選擇Cloud Functions for Firebase 。
- 通過在函數列表中單擊函數名稱來選擇函數。
- 單擊頂部菜單中的編輯圖標。
- 從標記為Memory allocated的下拉菜單中選擇一個內存分配。
- 單擊更多以顯示高級選項,並在超時文本框中輸入秒數。
- 單擊保存以更新函數。
覆蓋 CPU 默認值
最多分配 2GB 內存,Cloud Functions for Firebase(第 2 代)中的每個函數默認為一個 CPU,然後增加到 4 和 8GB 的 2 個 CPU。請注意,這與第一代默認行為有很大不同,可能導致低內存功能的成本略高,如下表所示:
內存分配 | 版本 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個 | 不適用 |
如果您希望為第二代函數保留第一代行為,請將第一代默認值設置為全局選項:
// Turn off Firebase defaults
setGlobalOptions({ cpu: 'gcfv1' });
對於 CPU 密集型功能,第二代提供了配置額外 CPU 的靈活性。您可以按功能提升 CPU,如下所示:
// Boost CPU in a function:
export const analyzeImage = onObjectFinalized({ cpu: 2 }, (event) => {
// computer vision goes here
});