Az Azure Cosmos DB Java SDK 4-es verziójú Api for NoSQL-fiókokkal való használatakor felmerülő problémák elhárítása

A KÖVETKEZŐRE VONATKOZIK: NoSQL

Fontos

Ez a cikk csak az Azure Cosmos DB Java SDK 4-ben történő hibaelhárítását ismerteti. További információért tekintse meg az Azure Cosmos DB Java SDK v4 kibocsátási megjegyzéseit, a Maven-adattárat és a teljesítményre vonatkozó tippeket . Ha jelenleg a v4-es verziónál régebbi verziót használ, a v4-re való frissítésről a Migrálás az Azure Cosmos DB Java SDK v4-es verziójára című útmutatóban olvashat.

Ez a cikk az Azure Cosmos DB Java SDK v4-hez készült Azure Cosmos DB for NoSQL-fiókokkal való használatakor felmerülő gyakori problémákat, kerülő megoldásokat, diagnosztikai lépéseket és eszközöket ismerteti. Az Azure Cosmos DB Java SDK v4 ü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:

A diagnosztika rögzítése

Az adatbázisoknak, a tárolóknak, az elemeknek és a lekérdezésválaszoknak van egy Diagnosztika tulajdonsága a Java v4 SDK-ban. Ez a tulajdonság az egyetlen kéréssel kapcsolatos összes információt rögzíti, beleértve az újrapróbálkozások vagy átmeneti hibák esetén is.

A diagnosztika sztringként lesz visszaadva. A sztring az egyes verziókkal együtt változik, mivel a különböző forgatókönyvek jobb hibaelhárítása érdekében javul. Az SDK minden egyes verziójánál előfordulhat, hogy a sztring megtöri a formátumát. Ne elemezd a sztringet a kompatibilitástörő módosítások elkerülése érdekében.

Az alábbi kódminta bemutatja, hogyan olvashatja el a diagnosztikai naplókat a Java V4 SDK használatával:

Fontos

Javasoljuk, hogy ellenőrizze a Java V4 SDK minimálisan ajánlott verzióját, és győződjön meg arról, hogy ezt a verziót vagy újabb verziót használja. Itt ellenőrizheti az ajánlott verziót.

Adatbázis-műveletek

CosmosDatabaseResponse databaseResponse = client.createDatabaseIfNotExists(databaseName);
CosmosDiagnostics diagnostics = databaseResponse.getDiagnostics();
logger.info("Create database diagnostics : {}", diagnostics); 

Tárolóműveletek

CosmosContainerResponse containerResponse = database.createContainerIfNotExists(containerProperties,
                  throughputProperties);
CosmosDiagnostics diagnostics = containerResponse.getDiagnostics();
logger.info("Create container diagnostics : {}", diagnostics);

Elemműveletek

// Write Item
CosmosItemResponse<Family> item = container.createItem(family, new PartitionKey(family.getLastName()),
                    new CosmosItemRequestOptions());
        
CosmosDiagnostics diagnostics = item.getDiagnostics();
logger.info("Create item diagnostics : {}", diagnostics);
        
// Read Item
CosmosItemResponse<Family> familyCosmosItemResponse = container.readItem(documentId,
                    new PartitionKey(documentLastName), Family.class);
        
CosmosDiagnostics diagnostics = familyCosmosItemResponse.getDiagnostics();
logger.info("Read item diagnostics : {}", diagnostics);

Lekérdezési műveletek

String sql = "SELECT * FROM c WHERE c.lastName = 'Witherspoon'";
        
CosmosPagedIterable<Family> filteredFamilies = container.queryItems(sql, new CosmosQueryRequestOptions(),
                    Family.class);
        
//  Add handler to capture diagnostics
filteredFamilies = filteredFamilies.handle(familyFeedResponse -> {
    logger.info("Query Item diagnostics through handle : {}", 
    familyFeedResponse.getCosmosDiagnostics());
});
        
//  Or capture diagnostics through iterableByPage() APIs.
filteredFamilies.iterableByPage().forEach(familyFeedResponse -> {
    logger.info("Query item diagnostics through iterableByPage : {}",
    familyFeedResponse.getCosmosDiagnostics());
});

Azure Cosmos DB-kivételek

try {
  CosmosItemResponse<Family> familyCosmosItemResponse = container.readItem(documentId,
                    new PartitionKey(documentLastName), Family.class);
} catch (CosmosException ex) {
  CosmosDiagnostics diagnostics = ex.getDiagnostics();
  logger.error("Read item failure diagnostics : {}", diagnostics);
}

A diagnosztika naplózása

A Java V4 SDK 4.43.0-s és újabb verziói támogatják a Cosmos Diagnostics automatikus naplózását minden kérés vagy hiba esetén, ha megfelelnek bizonyos feltételeknek. Az alkalmazásfejlesztők meghatározhatnak küszöbértékeket a késéshez (pont (létrehozás, olvasás, csere, upsert, javítás) vagy nem pontalapú műveletekhez (lekérdezés, változáscsatorna, tömeges és köteg)), a kérelem díjához és a hasznos adatok méretéhez. Ha a kérések túllépik ezeket a meghatározott küszöbértékeket, a rendszer automatikusan kibocsátja a kérelmek cosmos-diagnosztikáit.

Alapértelmezés szerint a Java v4 SDK automatikusan naplózza ezeket a diagnosztikákat egy adott formátumban. Ez azonban megváltoztatható a kezelőfelület implementálásával CosmosDiagnosticsHandler és saját egyéni diagnosztikai kezelő biztosításával.

CosmosDiagnosticsHandler Ezek CosmosDiagnosticsThresholds aztán felhasználhatók az objektumbanCosmosClientTelemetryConfig, amelyet át kell adni CosmosClientBuilder szinkronizálási vagy aszinkron ügyfél létrehozásakor.

MEGJEGYZÉS: Ezek a diagnosztikai küszöbértékek különböző diagnosztikákra vonatkoznak, beleértve a naplózást, a nyomkövetést és az ügyfél telemetriát.

Az alábbi kódminták bemutatják, hogyan definiálhatók a diagnosztikai küszöbértékek, az egyéni diagnosztikai naplózók, és hogyan használhatók az ügyfél telemetriai konfigurációjában:

Egyéni diagnosztikai küszöbértékek meghatározása

//  Create diagnostics threshold
CosmosDiagnosticsThresholds cosmosDiagnosticsThresholds = new CosmosDiagnosticsThresholds();
//  These thresholds are for demo purposes
//  NOTE: Do not use the same thresholds for production
cosmosDiagnosticsThresholds.setPayloadSizeThreshold(100_00);
cosmosDiagnosticsThresholds.setPointOperationLatencyThreshold(Duration.ofSeconds(1));
cosmosDiagnosticsThresholds.setNonPointOperationLatencyThreshold(Duration.ofSeconds(5));
cosmosDiagnosticsThresholds.setRequestChargeThreshold(100f);

Egyéni diagnosztikai kezelő definiálása

//  By default, DEFAULT_LOGGING_HANDLER can be used
CosmosDiagnosticsHandler cosmosDiagnosticsHandler = CosmosDiagnosticsHandler.DEFAULT_LOGGING_HANDLER;

//  App developers can also define their own diagnostics handler
cosmosDiagnosticsHandler = new CosmosDiagnosticsHandler() {
    @Override
    public void handleDiagnostics(CosmosDiagnosticsContext diagnosticsContext, Context traceContext) {
        logger.info("This is custom diagnostics handler: {}", diagnosticsContext.toJson());
    }
};

A CosmosClientTelemetryConfig definiálása

//  Create Client Telemetry Config
CosmosClientTelemetryConfig cosmosClientTelemetryConfig =
    new CosmosClientTelemetryConfig();
cosmosClientTelemetryConfig.diagnosticsHandler(cosmosDiagnosticsHandler);
cosmosClientTelemetryConfig.diagnosticsThresholds(cosmosDiagnosticsThresholds);

//  Create sync client
CosmosClient client = new CosmosClientBuilder()
    .endpoint(AccountSettings.HOST)
    .key(AccountSettings.MASTER_KEY)
    .clientTelemetryConfig(cosmosClientTelemetryConfig)
    .buildClient();

Újrapróbálkozás a tervezés során

A rugalmas alkalmazások Azure Cosmos DB SDK-kkal való tervezéséről szóló útmutatónkból megtudhatja, hogyan tervezhet rugalmas alkalmazásokat, és megtudhatja, hogy melyek az SDK újrapróbálkozási szemantikája.

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

A portál metrikáinak ellenőrzése

A portálmetrikák ellenőrzése segít megállapítani, hogy az ügyféloldali probléma vagy a szolgáltatással kapcsolatos probléma van-e. Ha például a metrikák nagy sebességű korlátozott kérelmeket tartalmaznak (HTTP-állapotkód: 429), ami azt jelenti, hogy a kérés szabályozva van, akkor ellenőrizze a kérelem sebességének túl nagy szakaszát.

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

A legjobb teljesítmény érdekében:

  • 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 50 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.
    • Ha az alkalmazást az Azure Kubernetes Service-ben futtatja, az Azure Monitor használatával monitorozhatja a processzorhasználatot.

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ó: Azure Cosmos DB Java SDK v4 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 10 000 és 20 000 közötti porttartományt, amelyet a közvetlen mód használ. Kövesse a gazdagép Csatlakozás ion korlátját is.

UnknownHostException

A UnknownHostException azt jelenti, hogy a Java-keretrendszer nem tudja feloldani az Azure Cosmos DB-végpont DNS-bejegyzését az érintett gépen. Ellenőrizze, hogy a gép meg tudja-e oldani a DNS-bejegyzést, vagy ha egyéni DNS-feloldó szoftverrel (például VPN-sel vagy proxyval vagy egyéni megoldással) rendelkezik, győződjön meg arról, hogy a dns-végpont megfelelő konfigurációját tartalmazza, hogy a hiba nem oldható fel. Ha a hiba állandó, egy paranccsal ellenőrizheti a gép DNS-feloldását curl a hibában leírt végpont felé.

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-val 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, amely elemeket ad hozzá egy tárolóhoz (itt talál útmutatást az adatbázis és a tároló beállításához.) 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.

Java SDK V4 (Maven com.azure::azure-cosmos) Async API


//Bad code with read timeout exception

int requestTimeoutInSeconds = 10;

/* ... */

AtomicInteger failureCount = new AtomicInteger();
// Max number of concurrent item inserts is # CPU cores + 1
Flux<Family> familyPub =
        Flux.just(Families.getAndersenFamilyItem(), Families.getAndersenFamilyItem(), Families.getJohnsonFamilyItem());
familyPub.flatMap(family -> {
    return container.createItem(family);
}).flatMap(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) {
    }
    return Mono.empty();
}).doOnError(Exception.class, exception -> {
    failureCount.incrementAndGet();
}).blockLast();
assert(failureCount.get() > 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.

Java SDK V4 (Maven com.azure::azure-cosmos) Async API

// Have a singleton instance of an executor and a scheduler.
ExecutorService ex  = Executors.newFixedThreadPool(30);
Scheduler customScheduler = Schedulers.fromExecutor(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 .publishOn(customScheduler) .

Java SDK V4 (Maven com.azure::azure-cosmos) Async API

container.createItem(family)
        .publishOn(customScheduler) // Switches the thread.
        .subscribe(
                // ...
        );

A használatával publishOn(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 .

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.

  • Backoff implementálása getRetryAfterInMilliseconds időközönként

    A teljesítménytesztelés során növelnie kell a terhelést, amíg a kérések kis száma nem lesz szabályozva. Ha szabályozva van, az ügyfélalkalmazásnak vissza kell adnia a kiszolgáló által megadott újrapróbálkozási időközt. A visszalépés tiszteletben tartása biztosítja, hogy minimális időt töltsön várakozással az újrapróbálkozások között.

Hibakezelés a Java SDK reaktív láncából

Az Azure Cosmos DB Java SDK-ból származó hibakezelés fontos az ügyfél alkalmazáslogikája szempontjából. A reaktormag-keretrendszer különböző hibakezelési mechanizmusokat biztosít, amelyek különböző forgatókönyvekben használhatók. Azt javasoljuk az ügyfeleknek, hogy részletesen megértsék ezeket a hibakezelő operátorokat, és az újrapróbálkozások logikai forgatókönyveinek leginkább megfelelőket használják.

Fontos

Nem javasoljuk az operátor használatát onErrorContinue() , mivel ez nem minden esetben támogatott. Vegye figyelembe, hogy onErrorContinue() egy speciális operátor, amely nem egyértelművé teheti a reaktív lánc viselkedését. A felsőbb rétegbeli, nem az alsóbb rétegbeli operátorokon működik, speciális operátori támogatást igényel a működéshez, és a hatókör könnyen propagálja a felsőbb réteget olyan kódtárkódba, amely nem számított rá (ami nem szándékos viselkedést eredményez). A speciális operátorral kapcsolatos további részletekért tekintse meg a dokumentációtonErrorContinue().

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

Az Azure Cosmos DB Java SDK számos függőségben lekéri; Általánosságban elmondható, hogy ha a projekt függőségi fája tartalmaz egy olyan összetevő régebbi verzióját, amelytől az Azure Cosmos DB Java SDK függ, ez váratlan hibákat okozhat az alkalmazás futtatásakor. Ha azt vizsgálja, hogy az alkalmazás miért okozott váratlanul kivételt, érdemes ellenőrizni, hogy a függőségi fa nem véletlenül húzza-e be az Azure Cosmos DB Java SDK-függőségeinek egy vagy több régebbi verzióját.

Egy ilyen probléma kerülő megoldása, ha azonosítja, hogy a projektfüggőségek közül melyik a régi verzió, és kizárja az adott régebbi verzió tranzitív függőségét, és engedélyezi az Azure Cosmos DB Java SDK-nak, hogy az újabb verziót is bevezhesse.

Annak megállapításához, hogy a projektfüggőségek közül melyik tartalmaz egy régebbi verziót, amelytől az Azure Cosmos DB Java SDK függ, futtassa a következő parancsot a projekt pom.xml fájlon:

mvn dependency:tree

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

Ha már tudja, hogy a projekt melyik függősége függ egy régebbi verziótól, módosíthatja a lib függőségét a pom-fájlban, és kizárhatja a tranzitív függőséget az alábbi példában (amely feltételezi, hogy a reaktormag az elavult függőség):

<dependency>
  <groupId>${groupid-of-lib-which-brings-in-reactor}</groupId>
  <artifactId>${artifactId-of-lib-which-brings-in-reactor}</artifactId>
  <version>${version-of-lib-which-brings-in-reactor}</version>
  <exclusions>
    <exclusion>
      <groupId>io.projectreactor</groupId>
      <artifactId>reactor-core</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

Az Azure Cosmos DB Java SDK v4 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 INFO and its only appender to A1.
log4j.rootLogger=INFO, A1

log4j.category.com.azure.cosmos=INFO
#log4j.category.io.netty=OFF
#log4j.category.io.projectreactor=OFF
# 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

Windows rendszeren ugyanazt a parancsot futtathatja különböző argumentumjelölőkkel:

netstat -abn

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 .

Gyakori lekérdezési problémák

A lekérdezési metrikák segítenek meghatározni, hogy a lekérdezés hol tölti az idő nagy részét. A lekérdezési metrikákból láthatja, hogy a rendszer mennyit költ a háttérrendszerre és az ügyfélre. További információ a lekérdezés teljesítményére vonatkozó útmutatóról.

Következő lépések