Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Importante
Esse não é o SDK de Java mais recente para Azure Cosmos DB! Você deve atualizar seu projeto para o SDK do Java v4 do Azure Cosmos DB e ler o guia de solução de problemas do SDK do Java v4 do Azure Cosmos DB. Siga as instruções no guia Migrar para o Azure Cosmos DB Java SDK v4 e no guia Reactor vs RxJava para atualizar.
Este artigo aborda a solução de problemas somente para o SDK Assíncrono de Java do Azure Cosmos DB v2. Consulte as Notas de Versão do SDK Java Assíncrono do Azure Cosmos DB v2, o repositório Maven e Dicas de Desempenho para obter mais informações.
Importante
Em 31 de agosto de 2024, o SDK do Java Assíncrono do Azure Cosmos DB v2.x será desativado; o SDK e todos os aplicativos que usam o SDK continuarão funcionando; O Azure Cosmos DB simplesmente deixará de fornecer mais manutenção e suporte para esse SDK. É recomendável seguir as instruções acima para migrar para o SDK do Java do Azure Cosmos DB v4.
Este artigo aborda problemas comuns, soluções alternativas, etapas de diagnóstico e ferramentas ao usar o SDK assíncrono java com o Azure Cosmos DB para contas NoSQL. O SDK do Java Async fornece representação lógica do lado do cliente para acessar o Azure Cosmos DB para NoSQL. Este artigo descreve as ferramentas e as abordagens para ajudá-lo se você tiver algum problema.
Comece com esta lista:
- Dê uma olhada na seção Problemas comuns e soluções alternativas neste artigo.
- Examine o SDK, que está disponível em software livre no GitHub. Ele tem uma seção de problemas que é monitorada ativamente. Verifique se você encontrar algum problema semelhante com uma solução alternativa já arquivada.
- Examine dicas de desempenho e siga as práticas sugeridas.
- Leia o restante deste artigo, se você não encontrou uma solução. Em seguida, registre um problema no GitHub.
Problemas comuns e soluções alternativas
Problemas de rede, falha de tempo limite de leitura do Netty, baixa taxa de transferência, alta latência
Sugestões gerais
- Verifique se o aplicativo está em execução na mesma região que sua conta do Azure Cosmos DB.
- Verifique o uso da CPU no host em que o aplicativo está sendo executado. Se o uso da CPU for de 90% ou mais, execute seu aplicativo em um host com uma configuração mais alta. Ou você pode distribuir a carga em mais computadores.
Limitação de conexão
A limitação de conexão pode acontecer devido a um limite de conexão em um computador host ou ao esgotamento da porta do Azure SNAT (PAT).
Limite de conexão em um computador host
Alguns sistemas Linux, como o Red Hat, têm um limite superior no número total de arquivos abertos. Soquetes no Linux são implementados como arquivos, portanto, esse número também limita o número total de conexões. Execute o comando a seguir.
ulimit -a
O número máximo de arquivos abertos permitidos, identificados como "nofile", precisa ser pelo menos o dobro do tamanho do pool de conexões. Para obter mais informações, consulte dicas de desempenho.
Esgotamento da porta do Azure SNAT (PAT)
Se seu aplicativo for implantado em Máquinas Virtuais do Azure sem um endereço IP público, por padrão, as portas SNAT do Azure estabelecerão conexões com qualquer ponto de extremidade fora da VM. O número de conexões permitidas da VM para o ponto de extremidade do Azure Cosmos DB é limitado pela configuração do Azure SNAT.
As portas SNAT do Azure são usadas somente quando sua VM tem um endereço IP privado e um processo da VM tenta se conectar a um endereço IP público. Há duas soluções alternativas para evitar a limitação do SNAT do Azure:
Adicione seu ponto de extremidade de serviço do Azure Cosmos DB para a sub-rede da sua rede virtual de Máquinas Virtuais do Azure. Para saber mais, consulte pontos de extremidade de serviço de Rede Virtual do Microsoft Azure.
Quando o endpoint do serviço está habilitado, as solicitações não são mais enviadas de um IP público para o Azure Cosmos DB. Em vez disso, a rede virtual e a identidade de sub-rede são enviadas. Essa alteração poderá resultar em quedas de firewall se apenas IPs públicos forem permitidos. Se você usar um firewall, ao habilitar o ponto de extremidade de serviço, adicione uma sub-rede ao firewall usando as ACLs de Rede Virtual.
Atribua um IP público à VM do Azure.
Não é possível acessar o Serviço – firewall
ConnectTimeoutException indica que o SDK não pode acessar o serviço.
Você pode obter uma falha semelhante à seguinte ao usar o modo direto:
GoneException{error=null, resourceAddress='https://cdb-ms-prod-westus-fd4.documents.azure.com:14940/apps/e41242a5-2d71-5acb-2e00-5e5f744b12de/services/d8aa21a5-340b-21d4-b1a2-4a5333e7ed8a/partitions/ed028254-b613-4c2a-bf3c-14bd5eb64500/replicas/131298754052060051p//', statusCode=410, message=Message: The requested resource is no longer available at the server., getCauseInfo=[class: class io.netty.channel.ConnectTimeoutException, message: connection timed out: cdb-ms-prod-westus-fd4.documents.azure.com/101.13.12.5:14940]
Se você tiver um firewall em execução na sua máquina de aplicativo, abra o intervalo de portas de 10.000 a 20.000 que é usado pelo modo direto. Siga também o limite de conexão em um computador host.
Proxy HTTP
Se você usar um proxy HTTP, certifique-se que pode suportar o número de conexões configuradas no SDK ConnectionPolicy.
Caso contrário, você enfrentará problemas de conexão.
Padrão de codificação inválido: Bloquear o thread de E/S do Netty
O SDK usa a biblioteca de E/S do Netty para se comunicar com o Azure Cosmos DB. O SDK tem APIs Assíncronas e usa APIs de E/S sem bloqueio do Netty. O trabalho de E/S do SDK é executado em threads do IO Netty. O número de threads do IO Netty é configurado para ser o mesmo que o número de núcleos de CPU do computador de aplicativo.
Os threads de E/S do Netty devem ser usados apenas para o trabalho de E/S do Netty sem bloqueio. O SDK retorna o resultado da invocação de API em um dos threads de E/S do Netty para o código do aplicativo. Se o aplicativo executar uma operação de longa duração depois de receber resultados no thread do Netty, o SDK poderá não ter threads de E/S suficientes para executar seu trabalho de E/S interno. Essa codificação de aplicativo pode resultar em baixa taxa de transferência, alta latência e io.netty.handler.timeout.ReadTimeoutException falhas. A solução alternativa é alternar o thread quando você souber que a operação leva tempo.
Por exemplo, dê uma olhada no snippet de código a seguir. Você pode executar um trabalho de longa duração que leva mais de alguns milissegundos no thread do Netty. Em caso afirmativo, você poderá entrar em um estado em que nenhum thread de E/S do Netty está presente para realizar operações de E/S. Como resultado, você obtém uma falha de ReadTimeoutException.
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
@Test
public void badCodeWithReadTimeoutException() throws Exception {
int requestTimeoutInSeconds = 10;
ConnectionPolicy policy = new ConnectionPolicy();
policy.setRequestTimeoutInMillis(requestTimeoutInSeconds * 1000);
AsyncDocumentClient testClient = new AsyncDocumentClient.Builder()
.withServiceEndpoint(TestConfigurations.HOST)
.withMasterKeyOrResourceToken(TestConfigurations.MASTER_KEY)
.withConnectionPolicy(policy)
.build();
int numberOfCpuCores = Runtime.getRuntime().availableProcessors();
int numberOfConcurrentWork = numberOfCpuCores + 1;
CountDownLatch latch = new CountDownLatch(numberOfConcurrentWork);
AtomicInteger failureCount = new AtomicInteger();
for (int i = 0; i < numberOfConcurrentWork; i++) {
Document docDefinition = getDocumentDefinition();
Observable<ResourceResponse<Document>> createObservable = testClient
.createDocument(getCollectionLink(), docDefinition, null, false);
createObservable.subscribe(r -> {
try {
// Time-consuming work is, for example,
// writing to a file, computationally heavy work, or just sleep.
// Basically, it's anything that takes more than a few milliseconds.
// Doing such operations on the IO Netty thread
// without a proper scheduler will cause problems.
// The subscriber will get a ReadTimeoutException failure.
TimeUnit.SECONDS.sleep(2 * requestTimeoutInSeconds);
} catch (Exception e) {
}
},
exception -> {
//It will be io.netty.handler.timeout.ReadTimeoutException.
exception.printStackTrace();
failureCount.incrementAndGet();
latch.countDown();
},
() -> {
latch.countDown();
});
}
latch.await();
assertThat(failureCount.get()).isGreaterThan(0);
}
A solução alternativa é alterar o thread no qual você executa um trabalho que leva tempo. Defina uma instância singleton do agendador para seu aplicativo.
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
// Have a singleton instance of an executor and a scheduler.
ExecutorService ex = Executors.newFixedThreadPool(30);
Scheduler customScheduler = rx.schedulers.Schedulers.from(ex);
Talvez seja necessário fazer um trabalho que leve tempo, por exemplo, trabalho computacionalmente pesado ou bloqueio de E/S. Nesse caso, alterne o thread para um worker fornecido pelo seu customScheduler usando a API .observeOn(customScheduler).
SDK do Java Assíncrono V2 (Maven com.microsoft.azure::azure-cosmosdb)
Observable<ResourceResponse<Document>> createObservable = client
.createDocument(getCollectionLink(), docDefinition, null, false);
createObservable
.observeOn(customScheduler) // Switches the thread.
.subscribe(
// ...
);
Ao usar observeOn(customScheduler), você libera o thread de E/S do Netty e alterna para seu próprio thread personalizado fornecido pelo agendador personalizado.
Essa modificação resolve o problema. Você não terá mais um io.netty.handler.timeout.ReadTimeoutException fracasso.
Problema de esgotamento do pool de conexões
PoolExhaustedException é uma falha do lado do cliente. Essa falha indica que a carga de trabalho do aplicativo é maior do que o pool de conexões do SDK pode servir. Aumente o tamanho do pool de conexões ou distribua a carga em vários aplicativos.
Taxa de solicitações muito alta
Essa falha é uma falha no lado do servidor. Indica que você consumiu sua taxa de transferência provisionada. Tente novamente mais tarde. Se você encontrar esse erro com frequência, considere aumentar a capacidade de processamento da coleção.
Falha ao conectar-se ao Emulador do Azure Cosmos DB
O certificado HTTPS do Emulador do Azure Cosmos DB é autoassinado. Para que o SDK trabalhe com o emulador, importe o certificado do emulador para um Java TrustStore. Para obter mais informações, consulte Exportar certificados do Emulador do Azure Cosmos DB.
Problemas de conflito de dependência
Exception in thread "main" java.lang.NoSuchMethodError: rx.Observable.toSingle()Lrx/Single;
A exceção acima sugere que você tem uma dependência de uma versão mais antiga do RxJava lib (por exemplo, 1.2.2). Nosso SDK depende do RxJava 1.3.8, que tem APIs não disponíveis na versão anterior do RxJava.
A solução alternativa para esses problemas é identificar qual outra dependência traz o RxJava-1.2.2 e excluir a dependência transitiva no RxJava-1.2.2 e permitir que o SDK do CosmosDB traga a versão mais recente.
Para identificar qual biblioteca traz o RxJava-1.2.2, execute o seguinte comando ao lado do arquivo pom.xml do projeto:
mvn dependency:tree
Para obter mais informações, consulte o guia da árvore de dependência do maven.
Depois de identificar RxJava-1.2.2 como uma dependência transitiva de qual outra dependência do seu projeto, você pode modificar a dependência dessa biblioteca em seu arquivo pom e excluir a dependência transitiva RxJava.
<dependency>
<groupId>${groupid-of-lib-which-brings-in-rxjava1.2.2}</groupId>
<artifactId>${artifactId-of-lib-which-brings-in-rxjava1.2.2}</artifactId>
<version>${version-of-lib-which-brings-in-rxjava1.2.2}</version>
<exclusions>
<exclusion>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
</exclusion>
</exclusions>
</dependency>
Para obter mais informações, consulte o guia excluir dependência transitiva.
Habilitar o registro em log do SDK do cliente
O SDK Java Async usa o SLF4j como fachada de registro, que dá suporte ao log em frameworks de log populares, como log4j e logback.
Por exemplo, se você quiser usar log4j como a estrutura de log, adicione as seguintes libs em seu classpath Java.
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
Adicione também uma configuração do log4j.
# this is a sample log4j configuration
# Set root logger level to DEBUG and its only appender to A1.
log4j.rootLogger=INFO, A1
log4j.category.com.microsoft.azure.cosmosdb=DEBUG
#log4j.category.io.netty=INFO
#log4j.category.io.reactivex=INFO
# A1 is set to be a ConsoleAppender.
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %5X{pid} [%t] %-5p %c - %m%n
Para obter mais informações, consulte o manual de log sfl4j.
Estatísticas de rede do sistema operacional
Execute o comando netstat para ter uma noção de quantas conexões estão em estados como ESTABLISHED e CLOSE_WAIT.
No Linux, você pode executar o comando a seguir.
netstat -nap
Filtre o resultado somente para conexões com o endpoint do Azure Cosmos DB.
O número de conexões com o ponto de extremidade do Azure Cosmos DB no estado ESTABLISHED não pode ser maior do que o tamanho do pool de conexões configurado.
Muitas conexões com o endpoint do Azure Cosmos DB podem estar no estado CLOSE_WAIT. Pode haver mais de 1.000. Um número alto indica que as conexões são estabelecidas e interrompidas rapidamente. Essa situação potencialmente causa problemas. Para obter mais informações, consulte a seção Problemas comuns e soluções alternativas .