As instâncias de biblioteca de cliente são reutilizáveis e projetadas para durar muito tempo. Normalmente, os aplicativos mantêm uma única instância de uma biblioteca de cliente, em vez de criar uma biblioteca para cada solicitação.
Usando o Java-KMS como exemplo, o snippet a seguir mostra várias solicitações sendo invocadas com a mesma instância de cliente:
// 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();
Encerrar um cliente
A forma de gerenciar o ciclo de vida de um cliente depende do caso de uso e da biblioteca de cliente específica. Por exemplo, se você estiver usando um framework, siga as
diretrizes dele para gerenciamento de clientes. Embora alguns cenários possam usar
try-with-resources para clientes de curta duração, geralmente é recomendável reutilizar uma instância de cliente
de longa duração para eficiência.
Chamar close() em um cliente tenta um desligamento ordenado e garante que
as tarefas atuais continuem até a conclusão. O cliente não aceita novas tarefas. Se você não fechar o cliente, os recursos dele vão continuar persistindo, e seu aplicativo vai ter vazamentos de memória.
O exemplo a seguir usa o Java-KMS e mostra o fechamento do cliente:
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();
Além de close(), algumas bibliotecas de cliente Java expõem alguns métodos relacionados
para gerenciar o ciclo de vida do cliente:
shutdown(): equivalente aclose().shutdownNow(): invoca o processo de desligamento imediatamente. Interrompe todas as tarefas em execução e não aguarda a conclusão.isShutdown(): retornatruese as tarefas em segundo plano tiverem sido encerradas.isTerminated(): retornatruese todas as tarefas forem concluídas após o desligamento.awaitTermination(): bloqueia por um período até que todo o trabalho seja concluído após o desligamento.
Casos para vários clientes
Pode haver casos de uso específicos do cliente que justificam várias instâncias coexistentes de uma biblioteca de cliente. O principal caso de uso para ter vários clientes é quando há solicitações que precisam ser enviadas para vários endpoints diferentes. Uma instância de cliente se conecta a um único endpoint. Para se conectar a vários endpoints, crie um cliente para cada um deles.
Possíveis riscos para vários clientes
Há alguns riscos comuns em aplicativos que usam várias instâncias de biblioteca de cliente:
- Aumento do potencial de vazamentos de memória. Os recursos permanecem se nem todas as instâncias de cliente forem fechadas corretamente.
- Implicações no desempenho. Inicializar vários canais gRPC gera um custo de performance, que pode aumentar em aplicativos sensíveis à performance.
- Problemas com solicitações em trânsito. Fechar um cliente enquanto as solicitações ainda estão em andamento pode resultar em um
RejectedExecutionException. Verifique se as solicitações foram concluídas antes de fechar o cliente.