クライアント ライブラリ インスタンスは再利用可能で、長期にわたって使用できるように設計されています。通常、アプリケーションはリクエストごとにライブラリを作成するのではなく、クライアント ライブラリの単一インスタンスを維持します。
Java-KMS を例として、次のスニペットは、同じクライアント インスタンスで複数のリクエストが呼び出されることを示しています。
// 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();
クライアントを終了する
クライアントのライフサイクルを管理する方法は、ユースケースと特定のクライアント ライブラリによって異なります。たとえば、フレームワークを使用している場合は、クライアント管理に関するフレームワークのガイドラインに沿って対応します。一部のシナリオでは有効期間の短いクライアントに try-with-resources を使用する場合がありますが、一般的には効率を高めるために有効期間の長いクライアント インスタンスを再利用することをおすすめします。
クライアントで close() を呼び出すと、順序どおりのシャットダウンが試行され、既存のタスクが完了するまで継続されます。クライアントが新しいタスクを受け付けません。クライアントを閉じないと、リソースが存続し続け、アプリケーションでメモリリークが発生します。
次の例では、Java-KMS を使用してクライアントを閉じる方法を示します。
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();
close() に加えて、一部の Java クライアント ライブラリは、クライアントのライフサイクルを管理するための関連メソッドをいくつか公開しています。
shutdown():close()と同等。shutdownNow(): シャットダウン プロセスをすぐに呼び出します。実行中のすべてのタスクを停止し、タスクの完了を待機しません。isShutdown(): バックグラウンド タスクがシャットダウンされた場合はtrueを返します。isTerminated(): すべてのタスクがシャットダウン後に完了した場合、trueを返します。awaitTermination(): シャットダウン後にすべての作業が完了するまでブロックします。
複数のクライアントのケース
クライアント ライブラリの複数のインスタンスを共存させる必要がある特定のユースケースが存在する可能性があります。複数のクライアントを使用する主なユースケースは、複数の異なるエンドポイントに送信する必要があるリクエストがある場合です。クライアント インスタンスは単一のエンドポイントに接続します。複数のエンドポイントに接続するには、それぞれにクライアントを作成します。
マルチクライアントで発生し得るリスク
複数のクライアント ライブラリ インスタンスを使用するアプリケーションには、次のような一般的なリスクがあります。
- メモリリークの可能性が高まります。すべてのクライアント インスタンスが適切に閉じられていない場合、リソースは残ります。
- パフォーマンスへの影響。複数の gRPC チャネルを初期化すると、パフォーマンス コストが発生します。パフォーマンスが重要なアプリケーションでは、このコストが積み重なる可能性があります。
- 処理中のリクエストに関する問題。リクエストが処理中の状態でクライアントを閉じると、
RejectedExecutionExceptionが発生する可能性があります。クライアントを閉じる前に、リクエストが完了していることを確認します。