使用 AWS Lambda 函數的最佳做法 - AWS Lambda

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 AWS Lambda 函數的最佳做法

以下是使用 AWS Lambda的推薦最佳實務:

如需 Lambda 應用程式最佳實務的詳細資訊,請參閱無伺服器園地中的 應用程式設計。您也可以聯絡您的 AWS 客戶團隊並要求架構審查。

函數程式碼

  • 區隔 Lambda 處理常式與您的核心邏輯。能允許您製作更多可測單位的函式。在 Node.js 時,看起來會是這個樣子:

    exports.myHandler = function(event, context, callback) { var foo = event.foo; var bar = event.bar; var result = MyLambdaFunction (foo, bar); callback(null, result); } function MyLambdaFunction (foo, bar) { // MyLambdaFunction logic here }
  • 請利用執行環境重新使用來改看函式的效能。在函式處理常式之外初始化 SDK 用戶端和資料庫連線,並在本機快取 /tmp 目錄中的靜態資產。由您函式的相同執行個體處理的後續叫用可以重複使用這些資源。這可藉由減少函數執行時間來節省成本。

    若要避免叫用間洩漏潛在資料,請不要使用執行環境來儲存使用者資料、事件,或其他牽涉安全性的資訊。如果您的函式依賴無法存放在處理常式內記憶體中的可變狀態,請考慮為每個使用者建立個別函式或個別函式版本。

  • 使用 Keep-Alive 指令維持持續連線的狀態。Lambda 會隨著時間的推移清除閒置連線。叫用函數時嘗試重複使用閒置連線將導致連線錯誤。若要維護持續連線,請使用與執行階段相關聯的 keep-alive (保持啟用) 指令。如需範例,請參閱在 Node.js 中重複使用 Keep-Alive 的連線

  • 使用環境變數將操作參數傳遞給您的函數。例如,如果您正在寫入到 Amazon S3 儲存貯體,而非對您正在寫入的儲存貯體名稱進行硬式編碼,請將儲存貯體名稱設定為環境變數。

  • 控制函數部署套件內的相依性。 AWS Lambda 執行環境包含許多程式庫,例如 Node.js 和 Python 執行階段的 AWS SDK (完整清單可以在這裡找到:Lambda 執行期)。若要啟用最新的一組功能與安全更新,Lambda 會定期更新這些程式庫。這些更新可能會為您的 Lambda 函數行為帶來細微的變更。若要完全掌控您函式所使用的相依性,請利用部署套件封裝您的所有相依性。

  • 將部署套件最小化至執行時間所必要的套件大小。這能減少您的部署套件被下載與呼叫前解壓縮的時間。對於以 Java 或 .NET Core 編寫的函數,請避免將整個 AWS SDK 庫作為部署包的一部分上傳。或者,選擇性倚賴取得您需要的軟體開發套件元件的模組 (例如 DynamoDB、Amazon S3 開發套件模組,以及 Lambda 核心程式庫)。

  • 將相依性 .jar 檔案置於不同的 /lib 目錄,縮短 Lambda 解壓縮以 Java 撰寫之部署套件的時間。這比將您所有函式程式碼全部放入具大量 .class 檔案的單一 jar 更快速。如需說明,請參閱 使用 .zip 或 JAR 封存檔部署 Java Lambda 函數

  • 最小化依存項目的複雜性。偏好更簡易的框架,其可快速在執行環境啟動時載入。例如,偏好更簡易的 Java 相依性置入 (IoC) 架構如 DaggerGuice,勝於複雜的架構如 Spring Framework

  • 避免在您的 Lambda 函數中使用遞迴程式碼,其中函數會自動呼叫自己,直到符合一些任意的標準。這會導致意外的函式呼叫量與升高的成本。若您不小心這樣做,當更新程式碼時,請立刻將函式的預留並行設為 0,以調節對函式的所有呼叫。

  • 請勿在您的 Lambda 函數程式碼中使用未記錄的非公有 API。對於 AWS Lambda 受管執行階段,Lambda 會定期將安全性和功能更新套用至 Lambda 的內部 API。這些內部 API 更新可能是向後不相容的,這會導致意外結果,例如若您的函數依賴於這些非公有 API,則叫用失敗。請參閱 API 參考查看公開可用 API 的清單。

  • 撰寫等冪程式碼。為函數撰寫等冪程式碼可確保採用相同方式來處理重複事件。程式碼應正確驗證事件並正常處理重複的事件。如需詳細資訊,請參閱 How do I make my Lambda function idempotent? (如何讓 Lambda 函數等冪?)。

  • 避免使用 DNS 快取。Lambda 函數已快取 DNS 回應。如果您使用其他 DNS 快取,則可能會遇到連線逾時的情況。

    java.util.logging.Logger類別可間接啟用 JVM DNS 快取。若要覆寫預設設定,請在初始化之前將網路位址 .cache.ttl 設定為 0。 logger範例:

    public class MyHandler { // first set TTL property static{ java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); } // then instantiate logger var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class); }

    若要避免UnknownHostException失敗,建議您networkaddress.cache.negative.ttl將設定為 0。您可以使用AWS_LAMBDA_JAVA_NETWORKADDRESS_CACHE_NEGATIVE_TTL=0環境變數為 Lambda 函數設定此屬性。

    停用 JVM DNS 快取並不會停用 Lambda 的受管理 DNS 快取。

函數組態

  • 啟動您的 Lambda 函式的效能測試是確保您挑選最佳記憶體大小組態非常重要的一環。任何記憶體大小的增加能觸發相同的增加可用於函數的 CPU。函數的記憶體使用量是根據每次叫用來決定的,並且可以在 Amazon CloudWatch 中檢視。每一次呼叫會產生 REPORT: 項目,如下所示:

    REPORT RequestId: 3604209a-e9a3-11e6-939a-754dd98c7be3 Duration: 12.34 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 18 MB

    藉由分析 Max Memory Used: 欄位,您可以判斷您的函式是否需要更多記憶體,或是否過度佈建函式記憶體大小。

    若要尋找適合您功能的記憶體配置,我們建議您使用開放原始碼 AWS Lambda 電源調整專案。如需詳細資訊,請參閱開啟AWS Lambda 電源調整 GitHub。

    若要最佳化函數效能,我們也建議部署可充分利用進階向量延伸 2 (AVX2) 的程式庫。這可讓您處理繁重的工作負載,包括機器學習推論、媒體處理、高效能運算 (HPC)、科學模擬和財務建模。如需詳細資訊,請參閱使用 AVX2 建立更快的 AWS Lambda 函數

  • 對您的 Lambda 函數進行負載測試以判斷最佳的逾時值。分析您的函式執行多久時間是很重要的,如此您更能判斷任何相依服務的問題,這可能會增加超出預期的函式並行。當您的 Lambda 函數對可能無法處理 Lambda 擴展的資源發出網路呼叫時,這尤其重要。

  • 設定 IAM 政策時,使用最嚴苛的許可。了解您的 Lambda 函數需要的資源與操作,並限制這些許可的執行角色。如需詳細資訊,請參閱 Lambda 資源存取許可

  • 熟悉 Lambda 配額承載大小、檔案描述項與 /tmp 空間,是在判斷執行時間資源限制時經常忽略的。

  • 刪除您不再使用的 Lambda 函數。透過上述方法,未使用的函式不會對您的部署套件大小限制做不必要的計算。

  • 如果您使用 Amazon Simple Queue Service 作為事件來源,請確保函數的預期叫用時間值不會超過佇列上的可見性逾時值。這同時適用於CreateFunctionUpdateFunctionConfiguration

    • 在的情況下 CreateFunction,函數建立程序 AWS Lambda 將失敗。

    • 在的情況下 UpdateFunctionConfiguration,它可能會導致函數的重複調用。

功能擴充性

  • 熟悉您的上游和下游輸送量限制。雖然 Lambda 函數可隨負載進行無縫擴展,但上游和下游相依性可能不具有相同的輸送量能力。如果您需要限制函數可擴展的高度,則可以在函數上配置保留並發性。

  • 內置油門公差。如果您的同步函數因流量超過 Lambda 的擴展速率而遇到節流,您可以使用下列策略來改善節流容忍度:

    • 透過抖動來使用逾時、重試和輪詢。實作這些策略可以順利重試的呼叫,並協助確保 Lambda 可以在幾秒鐘內擴充,以將使用者限制降到最低。

    • 使用佈建的並行。佈建並行是 Lambda 配置給函數的預先初始化執行環境數目。Lambda 會在可用時使用佈建的並行處理傳入的要求。如果需要,Lambda 也可以將您的函數擴展到佈建的並行設定之外。設定佈建的並行功能會對您的帳戶產生額外費用 AWS 。

指標與警示

  • 使用使用 Lambda 函數指標 CloudWatch 警示,而不是從 Lambda 函數程式碼中建立或更新指標。這是追蹤 Lambda 函數運作狀態的更有效率方式,可讓您盡快在開發階段找出問題。例如,您可以根據預期的 Lambda 函數叫用持續時間來設定警示,以解決任何由函數程式碼導致的瓶頸或延遲。

  • 利用您的記錄程式庫與 AWS Lambda 指標與維度,找出應用程式錯誤 (例如,ERR、ERROR、WARNING 等等)。

  • 使用 AWS 成本異常偵測來偵測帳戶中的異常活動。成本異常偵測會使用機器學習來持續監控您的成本和使用量,同時盡可能減少誤報警示。「成本異常偵測」使用的資料可延遲長達 24 小時。 AWS Cost Explorer因此,使用後最多可能需要 24 小時才能偵測到異常。若要開始使用成本異常偵測,您必須先使用註冊 Cost Explorer。然後,存取成本異常偵測

使用串流

  • 使用不同的批次與記錄大小測試讓每個事件來源的輪詢頻率調整為函式可以多快完成作業。該CreateEventSourceMapping BatchSize 參數控制每次調用可以發送到函數的最大記錄數。更大的批次大小通常會更有效吸收更大集合的記錄的呼叫成本,增加您的傳輸量。

    Lambda 預設會在記錄可用時立即叫用函數。如果 Lambda 從事件來源中讀取的批次只有一筆記錄,Lambda 只會傳送一筆記錄至函數。為避免調用具有少量記錄的函數,您可設定批次間隔,請求事件來源緩衝記錄最長達五分鐘。調用函數之前,Lambda 會繼續從事件來源中讀取記錄,直到收集到完整批次、批次間隔到期或者批次達到 6 MB 的承載限制。如需詳細資訊,請參閱 批次處理行為

    警告

    Lambda 事件來源對應至少處理每個事件一次,並且可能會重複處理記錄。為了避免與重複事件相關的潛在問題,我們強烈建議您將函數代碼設為冪等。若要深入了解,請參閱 AWS 知識中心如何讓 Lambda 函數具有冪等性

  • 新增碎片以增加 Kinesis 串流處理輸送量。Kinesis 串流由一個或多個碎片組成。Lambda 會使用最多一個並行呼叫,輪詢每個碎片。例如,若您的串流有 100 個有效碎片,則會有最多 100 個 Lambda 函數叫用正在同時執行。增加碎片的數量會直接增加最大並行 Lambda 函數叫用的數量,還會增加 Kinesis 串流處理輸送量。如果您正在增加 Kinesis 串流中碎片的數量,請確保為您的資料挑選良好的分割區索引鍵 (請參閱分割區索引鍵),如此一來,相關的記錄會位於相同的碎片上,您的資料也會獲得妥善的分配。

  • 使用 Amazon CloudWatch on IteratorAge 來判斷您的 Kinesis 串流是否正在處理中。例如,將 CloudWatch 鬧鐘的上限設定為 30000 (30 秒)。

安全最佳實務

  • 使用監視與安全性最佳 AWS Lambda 作法相關的使用 AWS Security Hub。Security Hub 會透過安全控制來評估資源組態和安全標準,協助您遵守各種合規架構。如需使用 Security Hub 評估 Lambda 資源的詳細資訊,請參閱使用 AWS Security Hub 者指南中的AWS Lambda 控制項

  • 使用 Amazon Lambda 保護監控 GuardDuty Lambda 網路活動日誌 GuardDuty Lambda 保護可協助您識別潛在的安全威脅,當您的 AWS 帳戶. 例如,如果您的其中一個函數查詢與加密貨幣相關活動相關聯的 IP 地址。 GuardDuty 監控叫用 Lambda 函數時產生的網路活動記錄。若要進一步了解,請參閱 Amazon GuardDuty 使用者指南中的 Lambda 保護