As instâncias da biblioteca de cliente são reutilizáveis e projetadas para serem de longa duração. 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();
Fechar um cliente
A maneira como você gerencia o ciclo de vida de um cliente pode depender 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 aceitará novas tarefas. Se você não fechar o cliente, os recursos dele vão continuar persistindo, e o aplicativo vai gerar vazamentos de memória.
O exemplo a seguir usa o Java-KMS e mostra o cliente sendo fechado:
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 espera que a tarefa seja concluída.isShutdown(): retornatruese as tarefas em segundo plano tiverem sido desligadas.isTerminated(): retornatruese todas as tarefas tiverem sido 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 justifiquem 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.
Possíveis riscos de vários clientes
Há alguns riscos comuns com aplicativos que usam várias instâncias de biblioteca de cliente:
- Maior potencial de vazamentos de memória. Os recursos permanecem se nem todas as instâncias de cliente forem fechadas corretamente.
- Implicações de desempenho. A inicialização de vários canais gRPC gera um custo de desempenho, que pode aumentar em aplicativos sensíveis ao desempenho.
- Problemas com solicitações em trânsito. Fechar um cliente enquanto as solicitações ainda estão em trânsito pode levar a uma
RejectedExecutionException. Garanta que as solicitações sejam concluídas antes de fechar o cliente.