Az Azure Cosmos DB Async Java SDK v2 noSQL-fiókokhoz készült API-val való használatakor felmerülő problémák elhárítása

A KÖVETKEZŐRE VONATKOZIK: NoSQL

Fontos

Nem ez a legújabb Java SDK az Azure Cosmos DB-hez! Frissítse a projektet az Azure Cosmos DB Java SDK v4-re , majd olvassa el az Azure Cosmos DB Java SDK v4 hibaelhárítási útmutatóját. A frissítéshez kövesse a Migrate to Azure Cosmos DB Java SDK v4 útmutatójában és a Reactor vs RxJava útmutatóban található utasításokat.

Ez a cikk csak az Azure Cosmos DB Async Java SDK v2-hez kapcsolódó hibaelhárítást ismerteti. További információkért tekintse meg az Azure Cosmos DB Async Java SDK v2 kibocsátási megjegyzéseit, a Maven-adattárat és a teljesítményre vonatkozó tippeket .

Fontos

2024. augusztus 31-én megszűnik az Azure Cosmos DB Async Java SDK v2.x; az SDK és az SDK-t használó összes alkalmazás továbbra is működni fog; Az Azure Cosmos DB egyszerűen nem nyújt további karbantartást és támogatást ehhez az SDK-hoz. Javasoljuk, hogy kövesse a fenti utasításokat az Azure Cosmos DB Java SDK v4-be való migráláshoz.

Ez a cikk a Java Async SDK és az Azure Cosmos DB for NoSQL-fiókok használatakor előforduló gyakori problémákat, kerülő megoldásokat, diagnosztikai lépéseket és eszközöket ismerteti. A Java Async SDK ügyféloldali logikai reprezentációt biztosít az Azure Cosmos DB for NoSQL eléréséhez. Ez a cikk azokat az eszközöket és módszereket ismerteti, amelyek segítenek megoldani a problémákat.

Kezdje a következő listával:

Gyakori hibák és áthidaló megoldásaik

Hálózati problémák, Netty olvasási időtúllépési hiba, alacsony átviteli sebesség, nagy késés

Általános javaslatok

  • Győződjön meg arról, hogy az alkalmazás ugyanabban a régióban fut, mint az Azure Cosmos DB-fiókja.
  • Ellenőrizze a processzorhasználatot azon a gazdagépen, amelyen az alkalmazás fut. Ha a processzorhasználat 90 százalék vagy több, futtassa az alkalmazást egy magasabb konfigurációjú gazdagépen. Vagy több gépen is eloszthatja a terhelést.

Csatlakozás szabályozás

Csatlakozás szabályozás történhet egy gazdagép kapcsolati korlátja vagy az Azure SNAT (PAT) portkimerülése miatt.

Csatlakozás gazdagépre vonatkozó korlát

Egyes Linux-rendszerek, például a Red Hat, felső korlátot szabnak a megnyitott fájlok teljes számára. A Linux szoftvercsatornái fájlként vannak implementálva, így ez a szám a kapcsolatok teljes számát is korlátozza. Futtassa az alábbi parancsot.

ulimit -a

A "nofile" néven azonosított maximálisan engedélyezett megnyitott fájlok számának legalább a duplájára kell nőnie a kapcsolatkészlet méretének. További információ: Teljesítménytippek.

Az Azure SNAT (PAT) portkimerülése

Ha az alkalmazás nyilvános IP-cím nélküli Azure-beli virtuális gépeken van üzembe helyezve, az Azure SNAT-portok alapértelmezés szerint kapcsolatot létesítenek a virtuális gépen kívüli végpontokkal. A virtuális gépről az Azure Cosmos DB-végpontra engedélyezett kapcsolatok számát az Azure SNAT-konfiguráció korlátozza.

Az Azure SNAT-portok csak akkor használatosak, ha a virtuális gép magánhálózati IP-címmel rendelkezik, és a virtuális gép egy folyamata megpróbál csatlakozni egy nyilvános IP-címhez. Az Azure SNAT korlátozásának elkerülésére két áthidaló megoldás létezik:

  • Adja hozzá az Azure Cosmos DB szolgáltatásvégpontot az Azure Virtual Machines virtuális hálózat alhálózatához. További információ: Azure Virtual Network szolgáltatásvégpontok.

    Ha a szolgáltatásvégpont engedélyezve van, a rendszer nem küldi el a kéréseket nyilvános IP-címről az Azure Cosmos DB-nek. Ehelyett a rendszer elküldi a virtuális hálózatot és az alhálózati identitást. Ez a módosítás tűzfalleesést okozhat, ha csak nyilvános IP-címek engedélyezettek. Ha tűzfalat használ, a szolgáltatásvégpont engedélyezésekor adjon hozzá egy alhálózatot a tűzfalhoz virtuális hálózati ACL-ek használatával.

  • Nyilvános IP-cím hozzárendelése az Azure-beli virtuális géphez.

Nem érhető el a szolgáltatás – tűzfal

ConnectTimeoutException azt jelzi, hogy az SDK nem éri el a szolgáltatást. A következőhöz hasonló hibát kaphat a közvetlen mód használatakor:

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]

Ha az alkalmazásgépen tűzfal fut, nyissa meg a közvetlen mód által használt 10 000–20 000 porttartományt. Kövesse a gazdagép Csatlakozás ion korlátját is.

HTTP-proxy

HA HTTP-proxyt használ, győződjön meg arról, hogy támogatja az SDK-ban ConnectionPolicykonfigurált kapcsolatok számát. Ellenkező esetben csatlakozási problémákat tapasztal.

Érvénytelen kódolási minta: Netty IO-szál blokkolása

Az SDK a Netty IO-kódtár használatával kommunikál az Azure Cosmos DB-vel. Az SDK Async API-kkal rendelkezik, és a Netty nem blokkoló IO API-jait használja. Az SDK IO-munkája IO Netty-szálakon történik. Az IO Netty-szálak száma megegyezik az alkalmazásgép processzormagjainak számával.

A Netty IO-szálak csak nem blokkoló Netty IO-munka esetén használhatók. Az SDK az api-hívás eredményét adja vissza az alkalmazás kódjába az egyik Netty IO-szálon. Ha az alkalmazás hosszú távú műveletet hajt végre, miután eredményeket kap a Netty-szálon, előfordulhat, hogy az SDK-nak nincs elég IO-szála a belső I/O-munkához. Az ilyen alkalmazáskódolás alacsony átviteli sebességet, nagy késést és io.netty.handler.timeout.ReadTimeoutException hibákat eredményezhet. A megkerülő megoldás a szál váltása, ha tudja, hogy a művelet időt vesz igénybe.

Tekintse meg például a következő kódrészletet. Hosszú ideig tartó munkát végezhet, amely több mint néhány ezredmásodpercet vesz igénybe a Netty-szálon. Ha igen, végül olyan állapotba juthat, ahol nincs jelen Netty IO-szál az IO-munka feldolgozásához. Ennek eredményeképpen ReadTimeoutException hibát kap.

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);
}

A kerülő megoldás az, hogy módosítja azt a szálat, amelyen időt vesz igénybe. Az alkalmazás ütemezőjének egyetlen példányának definiálása.

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

Előfordulhat, hogy olyan munkát kell végeznie, amely időt vesz igénybe, például számításilag nehéz munkát, vagy blokkolja az I/O-t. Ebben az esetben váltson a szálra az API-val biztosított customScheduler feldolgozóra .observeOn(customScheduler) .

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(
            // ...
        );

A használatával observeOn(customScheduler)felszabadítja a Netty IO-szálat, és az egyéni ütemező által biztosított saját egyéni szálra vált. Ez a módosítás megoldja a problémát. Nem fog többé hibát kapni io.netty.handler.timeout.ReadTimeoutException .

Csatlakozás ion-készlet kimerült problémája

PoolExhaustedException egy ügyféloldali hiba. Ez a hiba azt jelzi, hogy az alkalmazás számítási feladatai magasabbak, mint amit az SDK-kapcsolatkészlet képes kiszolgálni. Növelje a kapcsolatkészlet méretét, vagy ossza el a terhelést több alkalmazáson.

Túl magas kérelemmennyiség

Ez a hiba kiszolgálóoldali hiba. Azt jelzi, hogy felhasználta a kiosztott átviteli sebességet. Próbálkozzon újra később. Ha ezt a hibát gyakran kapja meg, fontolja meg a gyűjtemény átviteli sebességének növelését.

Hiba történt az Azure Cosmos DB Emulatorhoz való csatlakozáskor

Az Azure Cosmos DB Emulator HTTPS-tanúsítványa önaláírt. Ahhoz, hogy az SDK működjön az emulátorsal, importálja az emulátortanúsítványt egy Java TrustStore-ba. További információ: Azure Cosmos DB Emulator-tanúsítványok exportálása.

Függőségi ütközésekkel kapcsolatos problémák

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

A fenti kivétel arra utal, hogy függősége van az RxJava lib egy régebbi verziójától (például 1.2.2). Az SDK az RxJava 1.3.8-ra támaszkodik, amely az RxJava korábbi verziójában nem érhető el API-kkal.

Az ilyen problémák kerülő megoldása annak azonosítása, hogy melyik más függőség hozza létre az RxJava-1.2.2-es verziót, és kizárja az RxJava-1.2.2 átmeneti függőségét, és engedélyezi a CosmosDB SDK-nak az újabb verziót.

Az RxJava-1.2.2 kódtárhoz tartozó kódtár azonosításához futtassa a következő parancsot a projekt pom.xml fájl mellett:

mvn dependency:tree

További információt a maven függőségfa útmutatójában talál.

Miután azonosította, hogy az RxJava-1.2.2 tranzitív függőség, amelynek a projekt más függősége, módosíthatja az adott lib függőségét a pom-fájlban, és kizárhatja az RxJava tranzitív függőségét:

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

További információkért tekintse meg a tranzitív függőségek kizárásával kapcsolatos útmutatót.

Ügyféloldali SDK-naplózás engedélyezése

A Java Async SDK az SLF4j-t használja naplózási homlokzatként, amely támogatja a népszerű naplózási keretrendszerekbe, például a log4j-be és a logbackbe való bejelentkezést.

Ha például a log4j-t szeretné naplózási keretrendszerként használni, adja hozzá a következő libeket a Java-osztályútvonalhoz.

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

Adjon hozzá egy log4j-konfigurációt is.

# 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

További információ: sfl4j naplózási kézikönyv.

Operációs rendszer hálózati statisztikái

Futtassa a netstat parancsot annak megtekintéséhez, hogy hány kapcsolat van az olyan állapotokban, mint a ESTABLISHED és CLOSE_WAIT.

Linuxon a következő parancsot futtathatja.

netstat -nap

Az eredmény szűrése csak az Azure Cosmos DB-végponttal létesített kapcsolatokra.

Az Állapotban lévő ESTABLISHED Azure Cosmos DB-végponthoz való kapcsolatok száma nem lehet nagyobb, mint a konfigurált kapcsolatkészlet mérete.

Előfordulhat, hogy az Azure Cosmos DB-végponthoz számos kapcsolat van állapotban CLOSE_WAIT . 1000-nél több is lehet. A magas szám azt jelzi, hogy a kapcsolatok gyorsan létrejönnek és megszakadnak. Ez a helyzet problémákat okozhat. További információkért tekintse meg a Gyakori problémák és kerülő megoldások szakaszt .