本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
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)