提示與技巧

本文檔介紹了設計、實施、測試和部署 Cloud Functions 的最佳實踐。

正確性

本節介紹設計和實施 Cloud Functions 的一般最佳實踐。

編寫冪等函數

即使您的函數被多次調用,它們也應該產生相同的結果。如果先前的調用在您的代碼中途失敗,這使您可以重試調用。有關詳細信息,請參閱重試後台函數

不啟動後台活動

後台活動是您的函數終止後發生的任何事情。一旦函數返回或以其他方式發出完成信號,例如通過調用 Node.js 後台函數中的callback參數,函數調用就完成了。優雅終止後運行的任何代碼都無法訪問 CPU,也不會取得任何進展。

此外,當在同一環境中執行後續調用時,您的後台活動會恢復,從而乾擾新的調用。這可能會導致難以診斷的意外行為和錯誤。在函數終止後訪問網絡通常會導致連接被重置( ECONNRESET錯誤代碼)。

後台活動通常可以在單個調用的日誌中檢測到,方法是查找在表示調用完成的行之後記錄的任何內容。後台活動有時可能會更深地隱藏在代碼中,尤其是在存在異步操作(例如回調或計時器)時。檢查您的代碼以確保在終止函數之前完成所有異步操作。

始終刪除臨時文件

臨時目錄中的本地磁盤存儲是內存中的文件系統。您編寫的文件會消耗函數可用的內存,並且有時會在調用之間持續存在。未能明確刪除這些文件最終可能會導致內存不足錯誤和隨後的冷啟動。

您可以通過在 GCP Console的函數列表中選擇單個函數並選擇內存使用情況圖來查看單個函數使用的內存。

不要嘗試在臨時目錄之外寫入,並確保使用平台/操作系統無關的方法來構建文件路徑。

使用流水線處理較大的文件時,您可以減少內存需求。例如,您可以通過創建讀取流、將其傳遞給基於流的進程並將輸出流直接寫入 Cloud Storage 來處理 Cloud Storage 上的文件。

工具

本節提供有關如何使用工具來實現、測試和與 Cloud Functions 交互的指南。

地方發展

函數部署需要一些時間,因此在本地測試函數的代碼通常會更快。

Firebase 開發人員可以使用Firebase CLI Cloud Functions Emulator

使用 Sendgrid 發送電子郵件

Cloud Functions 不允許端口 25 上的出站連接,因此您無法與 SMTP 服務器建立非安全連接。發送電子郵件的推薦方法是使用SendGrid 。您可以在 Google Compute Engine的從實例發送電子郵件教程中找到其他發送電子郵件的選項。

表現

本節介紹優化性能的最佳實踐。

明智地使用依賴項

因為函數是無狀態的,所以執行環境通常是從頭開始初始化的(在所謂的冷啟動期間)。當發生冷啟動時,將評估函數的全局上下文。

如果您的函數導入模塊,則這些模塊的加載時間可能會增加冷啟動期間的調用延遲。您可以通過正確加載依賴項而不加載函數不使用的依賴項來減少此延遲以及部署函數所需的時間。

使用全局變量在未來的調用中重用對象

不能保證雲函數的狀態將被保留以供將來調用。但是,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中了解有關優化性能的更多信息。