Runtime Java pour les instances gérées Lambda - AWS Lambda

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Runtime Java pour les instances gérées Lambda

Pour les environnements d'exécution Java, les instances gérées Lambda utilisent les threads du système d'exploitation à des fins de simultanéité. Lambda charge votre objet gestionnaire une fois par environnement d'exécution lors de l'initialisation, puis crée plusieurs threads. Ces threads s'exécutent en parallèle et nécessitent une gestion sûre de l'état et des ressources partagées. Chaque thread partage le même objet de gestionnaire et tous les champs statiques.

Configuration de la simultanéité

Le nombre maximum de demandes simultanées que Lambda envoie à chaque environnement d'exécution est contrôlé par le PerExecutionEnvironmentMaxConcurrency paramètre de configuration de la fonction. Ce paramètre est facultatif et la valeur par défaut varie en fonction du temps d'exécution. Pour les environnements d'exécution Java, la valeur par défaut est de 32 requêtes simultanées par vCPU, ou vous pouvez configurer votre propre valeur. Cette valeur détermine également le nombre de threads utilisés par le moteur d'exécution Java. Lambda ajuste automatiquement le nombre de demandes simultanées jusqu'au maximum configuré en fonction de la capacité de chaque environnement d'exécution à absorber ces demandes.

Création de fonctions pour la multisimultanéité

Vous devez appliquer les mêmes pratiques de sécurité des threads lorsque vous utilisez des instances gérées Lambda que dans tout autre environnement multithread. Étant donné que l'objet du gestionnaire est partagé entre tous les threads de travail d'exécution, tout état mutable doit être sûr pour les threads. Cela inclut les collections, les connexions aux bases de données et tous les objets statiques modifiés lors du traitement des demandes.

AWS Les clients du SDK sont compatibles avec les threads et ne nécessitent aucune manipulation particulière.

Exemple : pools de connexions aux bases de données

Le code suivant utilise un objet de connexion à une base de données statique partagé entre les threads. Selon la bibliothèque de connexion utilisée, cela peut ne pas être sûr pour les threads.

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(); } }

Une approche sûre dans les threads consiste à utiliser un pool de connexions. Dans l'exemple suivant, le gestionnaire de fonctions extrait une connexion du pool. La connexion n'est utilisée que dans le cadre d'une seule demande.

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(); } }

Exemple : Collections

Les collections Java standard ne sont pas sûres pour les threads :

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"; } }

Utilisez plutôt des collections adaptées aux threads :

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"; } }

Répertoire /tmp partagé

Le /tmp répertoire est partagé entre toutes les demandes simultanées dans l'environnement d'exécution. Les écritures simultanées dans le même fichier peuvent entraîner une corruption des données, par exemple si un autre processus remplace le fichier. Pour résoudre ce problème, implémentez le verrouillage des fichiers partagés ou utilisez des noms de fichiers uniques par thread ou par demande afin d'éviter les conflits. N'oubliez pas de nettoyer les fichiers inutiles pour ne pas épuiser l'espace disponible.

Logging

L'entrelacement des journaux (les entrées des journaux provenant de différentes demandes sont entrelacées dans des journaux) est normal dans les systèmes multiconcurrents.

Les fonctions utilisant des instances gérées Lambda utilisent toujours le format de journal JSON structuré introduit avec les contrôles de journalisation avancés. Ce format inclut lerequestId, ce qui permet de corréler les entrées du journal à une seule demande. Lorsque vous utilisez l'LambdaLoggerobjet decontext.getLogger(), requestId il est automatiquement inclus dans chaque entrée du journal. Pour plus d'informations, consultez la section Utilisation des contrôles de journalisation avancés Lambda avec Java.

Contexte de la requête

L'contextobjet est lié au fil de requête. L'utilisation context.getAwsRequestId() fournit un accès multithread à l'ID de demande pour la demande en cours.

context.getXrayTraceId()À utiliser pour accéder au X-Ray Trace ID. Cela fournit un accès sécurisé à l'ID de trace pour la demande en cours. Lambda ne prend pas en charge la variable d'_X_AMZN_TRACE_IDenvironnement avec les instances gérées par Lambda. Le X-Ray Trace ID est automatiquement propagé lors de l'utilisation du AWS SDK.

Si vous utilisez des threads virtuels dans votre programme ou si vous créez des threads lors de l'initialisation, vous devrez transmettre tout contexte de demande requis à ces threads.

Initialisation et arrêt

L'initialisation de la fonction a lieu une fois par environnement d'exécution. Les objets créés lors de l'initialisation sont partagés entre les threads.

Pour les fonctions Lambda avec extensions, l'environnement d'exécution émet un signal SIGTERM lors de l'arrêt. Ce signal est utilisé par les extensions pour déclencher des tâches de nettoyage, telles que le rinçage des tampons. Vous pouvez vous abonner aux événements SIGTERM pour déclencher des tâches de nettoyage des fonctions, telles que la fermeture des connexions aux bases de données. Pour en savoir plus sur le cycle de vie de l'environnement d'exécution, voir Comprendre le cycle de vie de l'environnement d'exécution Lambda.

Versions de dépendance

Les instances gérées Lambda nécessitent les versions de package minimales suivantes :

  • AWS SDK pour Java 2.0 : version 2.34.0 ou ultérieure

  • AWS SDK X-Ray pour Java : version 2.20.0 ou ultérieure

  • AWS Distro for OpenTelemetry - Instrumentation pour Java : version 2.20.0 ou ultérieure

  • Powertools pour AWS Lambda (Java) : version 2.8.0 ou ultérieure

Outils électriques pour AWS Lambda (Java)

Powertools for AWS Lambda (Java) est compatible avec les instances gérées par Lambda et fournit des utilitaires pour la journalisation, le suivi, les métriques, etc. Pour plus d'informations, consultez Powertools for AWS Lambda (Java).

Étapes suivantes