Gérer les cycles de vie des clients dans les bibliothèques clientes Java Cloud

Les instances de bibliothèque cliente sont réutilisables et conçues pour durer. En règle générale, les applications conservent une seule instance d'une bibliothèque cliente, plutôt que d'en créer une pour chaque requête.

En utilisant Java-KMS comme exemple, l'extrait de code suivant montre plusieurs requêtes appelées avec la même instance de client :

// Create one instance of KMS's KeyManagementServiceClient
KeyManagementServiceClient keyManagementServiceClient =
 KeyManagementServiceClient.create();
keyManagementServiceClient.listKeyRings();
keyManagementServiceClient.asymmetricSign();
keyManagementServiceClient.createCryptoKey();
// ... other code ...

// Create one instance of KMS's AutokeyClient
AutokeyClient autokeyClient = AutokeyClient.create();
autokeyClient.listKeyHandles();
autokeyClient.getKeyHandle();

Fermer un client

La façon dont vous gérez le cycle de vie d'un client peut dépendre du cas d'utilisation et de la bibliothèque cliente spécifique. Par exemple, si vous utilisez un framework, suivez ses consignes pour la gestion des clients. Bien que certains scénarios puissent utiliser try-with-resources pour les clients de courte durée, il est généralement recommandé de réutiliser une instance de client de longue durée pour plus d'efficacité.

L'appel de close() sur un client tente un arrêt ordonné et garantit que les tâches existantes se poursuivent jusqu'à leur achèvement. Le client n'acceptera pas de nouvelles tâches. Si vous ne fermez pas le client, ses ressources continuent d'exister et votre application subit des fuites de mémoire.

L'exemple suivant utilise Java-KMS et montre la fermeture du client :

KeyManagementServiceClient keyManagementServiceClient =
  KeyManagementServiceClient.create(keyManagementServiceSettings);
// ... other code ...
keyManagementServiceClient.close();

// For gRPC clients, it's recommended to call awaitTermination to ensure a
// graceful shutdown and avoid the following error message in the logs:
// ERROR i.g.i.ManagedChannelOrphanWrapper - *~*~*~ Channel ManagedChannelImpl
// was not shutdown properly!!! ~*~*~*
// java.lang.RuntimeException: ManagedChannel allocation site
// at io.grpc.internal.ManagedChannelOrphanWrapper$ManagedChannelReference.<init>
keyManagementServiceClient.awaitTermination(DURATION, TimeUnit.SECONDS);

// Optionally include a shutdownNow() call after awaitTermination() to force
// close any lingering resources
keyManagementServiceClient.shutdownNow();

En plus de close(), certaines bibliothèques clientes Java exposent quelques méthodes associées pour gérer le cycle de vie du client :

  • shutdown() : équivalent à close().
  • shutdownNow() : appelle immédiatement le processus d'arrêt. Arrête toutes les tâches en cours d'exécution et n'attend pas leur achèvement.
  • isShutdown() : renvoie true si les tâches en arrière-plan ont été arrêtées.
  • isTerminated(): renvoie true si toutes les tâches ont été effectuées après l'arrêt.
  • awaitTermination(): bloque pendant une durée jusqu'à ce que toutes les tâches soient terminées après l'arrêt.

Cas d'utilisation de plusieurs clients

Il peut exister des cas d'utilisation spécifiques des clients qui justifient plusieurs instances coexistantes d'une bibliothèque cliente. Le principal cas d'utilisation de plusieurs clients est celui où des requêtes doivent être envoyées à plusieurs points de terminaison différents. Une instance de client se connecte à un seul point de terminaison. Pour vous connecter à plusieurs points de terminaison, créez un client pour chacun d'eux.

Risques potentiels liés à l'utilisation de plusieurs clients

Voici quelques risques courants liés aux applications qui utilisent plusieurs instances de bibliothèque cliente :

  • Risque accru de fuites de mémoire. Les ressources persistent si toutes les instances de client ne sont pas correctement fermées.
  • Implications sur les performances. L'initialisation de plusieurs canaux gRPC entraîne un coût en termes de performances, qui peut s'accumuler dans les applications sensibles aux performances.
  • Problèmes liés aux requêtes en cours. La fermeture d'un client alors que des requêtes sont encore en cours peut entraîner une RejectedExecutionException. Assurez-vous que les requêtes sont terminées avant de fermer le client.