Share via


Problemen oplossen wanneer u de Azure Cosmos DB Async Java SDK v2 gebruikt met API voor NoSQL-accounts

VAN TOEPASSING OP: NoSQL

Belangrijk

Dit is niet de nieuwste Java SDK voor Azure Cosmos DB. U moet uw project upgraden naar Azure Cosmos DB Java SDK v4 en vervolgens de probleemoplossingsgids voor Azure Cosmos DB Java SDK v4 lezen. Volg de instructies in de handleiding Migreren naar Azure Cosmos DB Java SDK v4 en Reactor vs RxJava-handleiding om een upgrade uit te voeren.

In dit artikel vindt u informatie over het oplossen van problemen met alleen Azure Cosmos DB Async Java SDK v2. Zie de releaseopmerkingen voor Azure Cosmos DB Async Java SDK v2, Maven-opslagplaats en prestatietips voor meer informatie.

Belangrijk

Op 31 augustus 2024 wordt de Azure Cosmos DB Async Java SDK v2.x buiten gebruik gesteld; de SDK en alle toepassingen die gebruikmaken van de SDK blijven functioneren; Azure Cosmos DB biedt eenvoudigweg geen onderhoud meer en ondersteuning voor deze SDK. U wordt aangeraden de bovenstaande instructies te volgen om te migreren naar Azure Cosmos DB Java SDK v4.

In dit artikel worden veelvoorkomende problemen, tijdelijke oplossingen, diagnostische stappen en hulpprogramma's beschreven wanneer u de Java Async SDK gebruikt met Azure Cosmos DB for NoSQL-accounts. De Java Async SDK biedt logische weergave aan de clientzijde voor toegang tot Azure Cosmos DB for NoSQL. In dit artikel worden tools en benaderingen beschreven om u te helpen bij eventuele problemen.

Begin met deze lijst:

Veelvoorkomende problemen en tijdelijke oplossingen

Netwerkproblemen, time-outfout bij lezen van Netty, lage doorvoer, hoge latentie

Algemene suggesties

  • Zorg ervoor dat de app wordt uitgevoerd in dezelfde regio als uw Azure Cosmos DB-account.
  • Controleer het CPU-gebruik op de host waarop de app wordt uitgevoerd. Als het CPU-gebruik 90 procent of meer is, voert u uw app uit op een host met een hogere configuratie. Of u kunt de belasting op meer computers distribueren.

Verbindingsbeperking

Verbindingsbeperking kan optreden vanwege een verbindingslimiet op een hostcomputer of azure SNAT-poortuitputting (PAT).

Verbindingslimiet op een hostcomputer

Sommige Linux-systemen, zoals Red Hat, hebben een bovengrens voor het totale aantal geopende bestanden. Sockets in Linux worden geïmplementeerd als bestanden, dus dit aantal beperkt ook het totale aantal verbindingen. Voer de volgende opdracht uit.

ulimit -a

Het aantal maximaal toegestane geopende bestanden, die worden geïdentificeerd als 'nofile', moet ten minste een dubbele grootte hebben voor uw verbindingsgroep. Zie prestatietips voor meer informatie.

Poortuitputting van Azure SNAT (PAT)

Als uw app is geïmplementeerd op virtuele Azure-machines zonder een openbaar IP-adres, maken standaard Azure SNAT-poorten verbindingen met een eindpunt buiten uw VM. Het aantal verbindingen dat van de VM naar het Azure Cosmos DB-eindpunt is toegestaan, wordt beperkt door de Azure SNAT-configuratie.

Azure SNAT-poorten worden alleen gebruikt wanneer uw VIRTUELE machine een privé-IP-adres heeft en een proces van de VM probeert verbinding te maken met een openbaar IP-adres. Er zijn twee tijdelijke oplossingen om azure SNAT-beperking te voorkomen:

  • Voeg uw Azure Cosmos DB-service-eindpunt toe aan het subnet van uw virtuele Azure-machines-netwerk. Zie Azure Virtual Network-service-eindpunten voor meer informatie.

    Wanneer het service-eindpunt is ingeschakeld, worden de aanvragen niet meer verzonden vanaf een openbaar IP-adres naar Azure Cosmos DB. In plaats daarvan worden de identiteit van het virtuele netwerk en het subnet verzonden. Deze wijziging kan leiden tot een daling van de firewall als alleen openbare IP-adressen zijn toegestaan. Als u een firewall gebruikt en u het service-eindpunt inschakelt, voegt u een subnet toe aan de firewall met behulp van ACL's voor virtueel netwerk.

  • Wijs een openbaar IP-adres toe aan uw Azure-VM.

Kan de service niet bereiken - firewall

ConnectTimeoutException geeft aan dat de SDK de service niet kan bereiken. Er kan een fout optreden die vergelijkbaar is met het volgende wanneer u de directe modus gebruikt:

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]

Als u een firewall op uw app-computer uitvoert, opent u poortbereik 10.000 tot 20.000 dat wordt gebruikt door de directe modus. Volg ook de verbindingslimiet op een hostcomputer.

HTTP-proxy

Als u een HTTP-proxy gebruikt, moet u ervoor zorgen dat deze het aantal verbindingen ondersteunt dat is geconfigureerd in de SDK ConnectionPolicy. Anders ondervindt u verbindingsproblemen.

Ongeldig coderingspatroon: Netty IO-thread blokkeren

De SDK maakt gebruik van de Netty IO-bibliotheek om te communiceren met Azure Cosmos DB. De SDK heeft Async-API's en maakt gebruik van niet-blokkerende IO-API's van Netty. Het IO-werk van de SDK wordt uitgevoerd op IO Netty-threads. Het aantal IO Netty-threads is geconfigureerd om hetzelfde te zijn als het aantal CPU-kernen van de app-machine.

De Netty IO-threads zijn bedoeld om alleen te worden gebruikt voor niet-blokkerende Netty IO-werkzaamheden. De SDK retourneert het API-aanroepresultaat op een van de Netty IO-threads naar de code van de app. Als de app een langdurige bewerking uitvoert nadat deze resultaten heeft ontvangen op de Netty-thread, beschikt de SDK mogelijk niet over voldoende IO-threads om het interne IO-werk uit te voeren. Dergelijke app-codering kan leiden tot lage doorvoer, hoge latentie en io.netty.handler.timeout.ReadTimeoutException storingen. De tijdelijke oplossing is om de thread over te schakelen wanneer u weet dat de bewerking tijd kost.

Bekijk bijvoorbeeld het volgende codefragment. U kunt langdurig werken met meer dan een paar milliseconden in de Netty-thread. Zo ja, dan krijgt u uiteindelijk een status waarin geen Netty IO-thread aanwezig is om IO-werk te verwerken. Als gevolg hiervan krijgt u een ReadTimeoutException-fout.

Async Java SDK 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);
}

De tijdelijke oplossing is om de thread te wijzigen waarop u werk uitvoert dat tijd in beslag neemt. Definieer een singleton-exemplaar van de scheduler voor uw app.

Async Java SDK 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);

Mogelijk moet u werk doen dat bijvoorbeeld veel rekenkracht kost of I/O blokkeert. In dit geval schakelt u de thread over naar een werkrol die door uw customScheduler wordt geleverd met behulp van de .observeOn(customScheduler) API.

Async Java SDK V2 (Maven com.microsoft.azure::azure-cosmosdb)

Observable<ResourceResponse<Document>> createObservable = client
        .createDocument(getCollectionLink(), docDefinition, null, false);

createObservable
        .observeOn(customScheduler) // Switches the thread.
        .subscribe(
            // ...
        );

Met behulp van observeOn(customScheduler), laat u de Netty IO-thread los en schakelt u over naar uw eigen aangepaste thread die wordt geleverd door de aangepaste planner. Deze wijziging lost het probleem op. Je krijgt io.netty.handler.timeout.ReadTimeoutException geen storing meer.

Probleem met uitgeputte verbindingsgroep

PoolExhaustedException is een fout aan de clientzijde. Deze fout geeft aan dat uw app-workload hoger is dan wat de SDK-verbindingsgroep kan leveren. Vergroot de grootte van de verbindingsgroep of distribueer de belasting van meerdere apps.

Aanvraagsnelheid is te hoog

Deze fout is een fout aan de serverzijde. Dit geeft aan dat u de ingerichte doorvoer hebt verbruikt. Probeer het later opnieuw. Als u deze fout vaak krijgt, kunt u overwegen om de verzamelingsdoorvoer te verhogen.

Fout bij het maken van verbinding met Azure Cosmos DB Emulator

Het HTTPS-certificaat van Azure Cosmos DB Emulator is zelfondertekend. Voordat de SDK met de emulator werkt, importeert u het emulatorcertificaat in een Java TrustStore. Zie Azure Cosmos DB Emulator-certificaten exporteren voor meer informatie.

Problemen met afhankelijkheidsconflicten

Exception in thread "main" java.lang.NoSuchMethodError: rx.Observable.toSingle()Lrx/Single;

De bovenstaande uitzondering geeft aan dat u afhankelijk bent van een oudere versie van RxJava lib (bijvoorbeeld 1.2.2). Onze SDK is afhankelijk van RxJava 1.3.8 met API's die niet beschikbaar zijn in een eerdere versie van RxJava.

De tijdelijke oplossing voor dergelijke problemen is om te bepalen welke andere afhankelijkheid RxJava-1.2.2 oplevert en de transitieve afhankelijkheid van RxJava-1.2.2 uitsluit en cosmosDB SDK de nieuwere versie toestaat.

Als u wilt bepalen welke bibliotheek rxjava-1.2.2 bevat, voert u de volgende opdracht uit naast uw project pom.xml bestand:

mvn dependency:tree

Zie de handleiding voor de maven-afhankelijkheidsstructuur voor meer informatie.

Zodra u RxJava-1.2.2 hebt geïdentificeerd, is transitieve afhankelijkheid waarvan andere afhankelijkheid van uw project is, kunt u de afhankelijkheid van die lib in uw pom-bestand wijzigen en rxJava transitieve afhankelijkheid uitsluiten:

<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>

Zie de gids voor transitieve afhankelijkheid uitsluiten voor meer informatie.

Logboekregistratie van client-SDK inschakelen

De Java Async SDK maakt gebruik van SLF4j als de façade voor logboekregistratie die ondersteuning biedt voor logboekregistratie in populaire frameworks voor logboekregistratie, zoals log4j en logback.

Als u bijvoorbeeld log4j wilt gebruiken als logboekregistratieframework, voegt u de volgende bibliotheken toe in uw Java-klassepad.

<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>

Voeg ook een log4j-configuratie toe.

# 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

Zie de handleiding voor logboekregistratie van sfl4j voor meer informatie.

Statistieken van het besturingssysteemnetwerk

Voer de netstat-opdracht uit om een idee te krijgen van het aantal verbindingen in statussen zoals ESTABLISHED en CLOSE_WAIT.

In Linux kunt u de volgende opdracht uitvoeren.

netstat -nap

Filter het resultaat op alleen verbindingen met het Azure Cosmos DB-eindpunt.

Het aantal verbindingen met het Azure Cosmos DB-eindpunt in de status kan niet groter zijn dan de ESTABLISHED grootte van de geconfigureerde verbindingsgroep.

Veel verbindingen met het Azure Cosmos DB-eindpunt hebben mogelijk de CLOSE_WAIT status. Er kunnen meer dan 1.000 zijn. Een getal dat hoog aangeeft dat verbindingen tot stand zijn gebracht en snel worden uitgesplitst. Deze situatie veroorzaakt mogelijk problemen. Zie de sectie Veelvoorkomende problemen en tijdelijke oplossingen voor meer informatie.