클라이언트 라이브러리 인스턴스는 재사용 가능하며 수명이 길도록 설계되었습니다. 일반적으로 애플리케이션은 각 요청에 대해 라이브러리를 만드는 대신 클라이언트 라이브러리의 단일 인스턴스를 유지합니다.
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가 발생할 수 있습니다. 클라이언트를 닫기 전에 요청이 완료되었는지 확인합니다.