Lambda 受管執行個體的 Java 執行期 - AWS Lambda

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

Lambda 受管執行個體的 Java 執行期

對於 Java 執行期,Lambda 受管執行個體會使用作業系統執行緒來並行。Lambda 會在初始化期間為每個執行環境載入您的處理常式物件一次,然後建立多個執行緒。這些執行緒會平行執行,且需要安全處理狀態和共用資源的執行緒。每個執行緒共用相同的處理常式物件和任何靜態欄位。

並行組態

Lambda 傳送至每個執行環境的並行請求數目上限是由函數組態中的 PerExecutionEnvironmentMaxConcurrency設定所控制。這是選用設定,預設值會根據執行時間而有所不同。對於 Java 執行時間,預設值為每個 vCPU 32 個並行請求,或者您可以設定自己的值。此值也會決定 Java 執行時間使用的執行緒數目。Lambda 會根據每個執行環境的容量,自動調整並行請求的數量,直到設定的最大值為止,以吸收這些請求。

為多並行建置函數

使用 Lambda 受管執行個體時,您應該套用與任何其他多執行緒環境中相同的執行緒安全實務。由於處理常式物件會跨所有執行時間工作者執行緒共用,因此任何變動狀態都必須是執行緒安全。這包括集合、資料庫連線,以及在請求處理期間修改的任何靜態物件。

AWS SDK 用戶端是安全的執行緒,不需要特殊處理。

範例:資料庫連線集區

下列程式碼使用在執行緒之間共用的靜態資料庫連線物件。視使用的連線程式庫而定,這可能並不安全。

public class DBQueryHandler implements RequestHandler<Object, String> { // Single connection shared across all threads - NOT SAFE private static Connection connection; public DBQueryHandler() { this.connection = DriverManager.getConnection(jdbcUrl, username, password); } @Override public String handleRequest(Object input, Context context) { PreparedStatement stmt = connection.prepareStatement(query); ResultSet rs = stmt.executeQuery(); // Multiple threads using same connection causes issues return result.toString(); } }

安全執行緒的方法是使用連線集區。在下列範例中,函數處理常式會從集區擷取連線。連線僅用於單一請求的內容。

public class DBQueryHandler implements RequestHandler<Object, String> { private static HikariDataSource dataSource; public DBQueryHandler() { HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://localhost:3306/your_database"); dataSource = new HikariDataSource(config); // Create pool once per Lambda container } @Override public String handleRequest(Object input, Context context) { String query = "SELECT column_name FROM your_table LIMIT 10"; StringBuilder result = new StringBuilder("Data:\n"); // try-with-resources automatically calls close() on the connection, // which returns it to the HikariCP pool (does NOT close the physical DB connection) try (Connection connection = dataSource.getConnection(); PreparedStatement stmt = connection.prepareStatement(query); ResultSet rs = stmt.executeQuery()) { while (rs.next()) { result.append(rs.getString("column_name")).append("\n"); } } catch (Exception e) { context.getLogger().log("Error: " + e.getMessage()); return "Error"; } return result.toString(); } }

範例:集合

標準 Java 集合不安全執行緒:

public class Handler implements RequestHandler<Object, String> { private static List<String> items = new ArrayList<>(); private static Map<String, Object> cache = new HashMap<>(); @Override public String handleRequest(Object input, Context context) { items.add("list item"); // Not thread-safe cache.put("key", input); // Not thread-safe return "Success"; } }

請改用安全執行緒集合:

public class Handler implements RequestHandler<Object, String> { private static final List<String> items = Collections.synchronizedList(new ArrayList<>()); private static final ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>(); @Override public String handleRequest(Object input, Context context) { items.add("list item"); // Thread-safe cache.put("key", input); // Thread-safe return "Success"; } }

共用 /tmp 目錄

/tmp 目錄會在執行環境中所有並行請求之間共用。同時寫入相同檔案可能會導致資料損毀,例如,如果另一個程序覆寫檔案。若要解決此問題,請實作共用檔案的檔案鎖定,或針對每個執行緒或每個請求使用唯一的檔案名稱,以避免衝突。請記得清除不需要的檔案,以避免耗盡可用空間。

日誌

日誌交錯 (來自在日誌中交錯之不同請求的日誌項目) 在多並行系統中是正常的。

使用 Lambda 受管執行個體的函數一律使用進階記錄控制所引進的結構化 JSON 日誌格式。此格式包含 requestId,允許日誌項目與單一請求相關聯。當您使用來自 context.getLogger()LambdaLogger物件requestId時, 會自動包含在每個日誌項目中。如需詳細資訊,請參閱搭配 Java 使用 Lambda 進階記錄控制

請求內容

context 物件繫結至請求執行緒。使用 context.getAwsRequestId()可安全執行緒存取目前請求的請求 ID。

使用 context.getXrayTraceId() 存取 X-Ray 追蹤 ID。這可讓執行緒安全存取目前請求的追蹤 ID。Lambda 不支援具有 Lambda 受管執行個體_X_AMZN_TRACE_ID的環境變數。使用 AWS SDK 時,會自動傳播 X-Ray 追蹤 ID。

如果您在程式中使用虛擬執行緒或在初始化期間建立執行緒,您將需要將任何必要的請求內容傳遞至這些執行緒。

初始化和關閉

每個執行環境會發生一次函數初始化。在初始化期間建立的物件會跨執行緒共用。

對於具有擴充功能的 Lambda 函數,執行環境會在關閉期間發出 SIGTERM 訊號。延伸項目使用此訊號來觸發清除任務,例如排清緩衝區。您可以訂閱 SIGTERM 事件來觸發函數清除任務,例如關閉資料庫連線。若要進一步了解執行環境生命週期,請參閱了解 Lambda 執行環境生命週期

相依性版本

Lambda 受管執行個體需要下列最低套件版本:

  • AWS 適用於 Java 的 SDK 2.0:2.34.0 版或更新版本

  • AWS 適用於 Java 的 X-Ray 開發套件:2.20.0 版或更新版本

  • AWS Distro for OpenTelemetry - 適用於 Java 的檢測:2.20.0 版或更新版本

  • 適用於 AWS Lambda (Java) 的 Powertools:2.8.0 版或更新版本

Lambda 的 Powertools AWS (Java)

Powertools for AWS Lambda (Java) 與 Lambda 受管執行個體相容,並提供用於記錄、追蹤、指標等的公用程式。如需詳細資訊,請參閱 Powertools for AWS Lambda (Java)

後續步驟