Sdílet prostřednictvím


Výpis prostředků Azure Storage v C++

Výpis operací je klíčem k mnoha vývojovým scénářům se službou Azure Storage. Tento článek popisuje, jak nejefektivněji vytvořit výčet objektů ve službě Azure Storage pomocí rozhraní API výpisu, která jsou k dispozici v klientské knihovně Microsoft Azure Storage pro jazyk C++.

Poznámka:

Tato příručka cílí na klientskou knihovnu Azure Storage pro C++ verze 2.x, která je dostupná prostřednictvím NuGetu nebo GitHubu.

Klientská knihovna úložiště poskytuje různé metody pro výpis nebo dotazování objektů ve službě Azure Storage. Tento článek se zabývá následujícími scénáři:

  • Výpis kontejnerů v účtu
  • Výpis objektů blob v kontejneru nebo virtuálním adresáři objektů blob
  • Výpis front v účtu
  • Výpis tabulek v účtu
  • Dotazování entit v tabulce

Každá z těchto metod se zobrazuje pomocí různých přetížení pro různé scénáře.

Asynchronní versus synchronní

Vzhledem k tomu, že klientská knihovna úložiště pro jazyk C++ je založená na knihovně REST C++, podporujeme ze své podstaty asynchronní operace pomocí pplx ::task. Příklad:

pplx::task<list_blob_item_segment> list_blobs_segmented_async(continuation_token& token) const;

Synchronní operace zabalí odpovídající asynchronní operace:

list_blob_item_segment list_blobs_segmented(const continuation_token& token) const
{
    return list_blobs_segmented_async(token).get();
}

Pokud pracujete s více aplikacemi nebo službami s vlákny, doporučujeme používat asynchronní rozhraní API přímo místo vytváření vlákna k volání synchronizačních rozhraní API, což výrazně ovlivňuje váš výkon.

Segmentovaný výpis

Škálování cloudového úložiště vyžaduje segmentovaný výpis. Můžete mít například více než milion objektů blob v kontejneru objektů blob Azure nebo více než miliardu entit v tabulce Azure. Nejedná se o teoretická čísla, ale skutečné případy použití zákazníků.

Proto je nepraktické vypsat všechny objekty v jediné odpovědi. Místo toho můžete vypsat objekty pomocí stránkování. Každé z rozhraní API výpisu má segmentované přetížení.

Odpověď pro segmentovanou operaci výpisu zahrnuje:

  • _segment, která obsahuje sadu výsledků vrácených pro jedno volání rozhraní API výpisu.
  • continuation_token, který se předá dalšímu volání, aby se získala další stránka výsledků. Pokud se nevrátí žádné další výsledky, token pro pokračování má hodnotu null.

Například typické volání pro výpis všech objektů blob v kontejneru může vypadat jako následující fragment kódu. Kód je k dispozici v našich ukázkách:

// List blobs in the blob container
azure::storage::continuation_token token;
do
{
    azure::storage::list_blob_item_segment segment = container.list_blobs_segmented(token);
    for (auto it = segment.results().cbegin(); it != segment.results().cend(); ++it)
{
    if (it->is_blob())
    {
        process_blob(it->as_blob());
    }
    else
    {
        process_directory(it->as_directory());
    }
}

    token = segment.continuation_token();
}
while (!token.empty());

Všimněte si, že počet výsledků vrácených na stránce může být řízen parametrem max_results přetížením každého rozhraní API, například:

list_blob_item_segment list_blobs_segmented(const utility::string_t& prefix, bool use_flat_blob_listing,
    blob_listing_details::values includes, int max_results, const continuation_token& token,
    const blob_request_options& options, operation_context context)

Pokud nezadáte parametr max_results , vrátí se na jedné stránce výchozí maximální hodnota až 5 000 výsledků.

Všimněte si také, že dotaz na azure Table Storage nemusí vracet žádné záznamy nebo méně záznamů než hodnota zadaného parametru max_results , i když token pokračování není prázdný. Jedním z důvodů může být, že dotaz se během pěti sekund nepodařilo dokončit. Pokud token pokračování není prázdný, měl by dotaz pokračovat a váš kód by neměl předpokládat velikost výsledků segmentů.

Doporučený vzor kódování pro většinu scénářů je segmentovaný výpis, který poskytuje explicitní průběh výpisu nebo dotazování a způsob reakce služby na jednotlivé požadavky. Zejména u aplikací nebo služeb C++ může řízení průběhu výpisu na nižší úrovni pomoci řídit paměť a výkon.

Greedy listing

Starší verze klientské knihovny služby Storage pro C++ (verze 0.5.0 Preview a starší) obsahovaly nes segmentovaná rozhraní API pro tabulky a fronty, jak je znázorněno v následujícím příkladu:

std::vector<cloud_table> list_tables(const utility::string_t& prefix) const;
std::vector<table_entity> execute_query(const table_query& query) const;
std::vector<cloud_queue> list_queues() const;

Tyto metody byly implementovány jako obálky segmentovaných rozhraní API. Pro každou odpověď segmentovaného výpisu kód připojil výsledky k vektoru a vrátil všechny výsledky po kontrole celých kontejnerů.

Tento přístup může fungovat, když účet úložiště nebo tabulka obsahují malý počet objektů. S nárůstem počtu objektů by však požadovaná paměť mohla zvýšit bez omezení, protože všechny výsledky zůstaly v paměti. Jedna operace výpisu může trvat velmi dlouhou dobu, během které volající neměl žádné informace o jeho průběhu.

Tato rozhraní API pro zápis greedy v sadě SDK neexistují v prostředí C#, Java nebo JavaScriptu Node.js. Abychom se vyhnuli potenciálním problémům s používáním těchto greedy API, odebrali jsme je ve verzi 0.6.0 Preview.

Pokud váš kód volá tato rozhraní API greedy:

std::vector<azure::storage::table_entity> entities = table.execute_query(query);
for (auto it = entities.cbegin(); it != entities.cend(); ++it)
{
    process_entity(*it);
}

Pak byste měli upravit kód tak, aby používal segmentovaná rozhraní API výpisu:

azure::storage::continuation_token token;
do
{
    azure::storage::table_query_segment segment = table.execute_query_segmented(query, token);
    for (auto it = segment.results().cbegin(); it != segment.results().cend(); ++it)
    {
        process_entity(*it);
    }

    token = segment.continuation_token();
} while (!token.empty());

Zadáním parametru max_results segmentu můžete vyrovnávat počet požadavků a využití paměti, abyste splnili požadavky na výkon vaší aplikace.

Pokud navíc používáte segmentovaná rozhraní API pro výpis, ale data ukládáte do místní kolekce ve stylu "greedy", důrazně doporučujeme refaktorovat kód tak, aby zpracovával ukládání dat v místní kolekci pečlivě ve velkém měřítku.

Opožděný výpis

Ačkoli greedy výpis vyvolal potenciální problémy, je vhodné, pokud v kontejneru není příliš mnoho objektů.

Pokud používáte také sady C# nebo Oracle Java SDK, měli byste být obeznámeni s výčtovým programovacím modelem, který nabízí opožděný výpis, kde se data v určitém posunu načítají jenom v případě potřeby. V jazyce C++ poskytuje šablona založená na iterátoru také podobný přístup.

Typické opožděné rozhraní API, které jako příklad používá list_blobs , vypadá takto:

list_blob_item_iterator list_blobs() const;

Typický fragment kódu, který používá opožděný vzor výpisu, může vypadat takto:

// List blobs in the blob container
azure::storage::list_blob_item_iterator end_of_results;
for (auto it = container.list_blobs(); it != end_of_results; ++it)
{
    if (it->is_blob())
    {
        process_blob(it->as_blob());
    }
    else
    {
        process_directory(it->as_directory());
    }
}

Všimněte si, že opožděný výpis je k dispozici pouze v synchronním režimu.

V porovnání s greedy výpis, opožděný výpis načítá data pouze v případě potřeby. Pod kryty načte data ze služby Azure Storage pouze v případě, že se další iterátor přesune do dalšího segmentu. Proto je využití paměti řízeno ohraničovanou velikostí a operace je rychlá.

Opožděné výpis rozhraní API jsou součástí klientské knihovny úložiště pro C++ ve verzi 2.2.0.

Závěr

V tomto článku jsme probrali různé přetížení pro výpis rozhraní API pro různé objekty v klientské knihovně úložiště pro C++ . Shrnutí:

  • Asynchronní rozhraní API se důrazně doporučují ve scénářích s více vlákny.
  • Segmentovaný výpis se doporučuje pro většinu scénářů.
  • Lazy listing is provided in the library as a convenient wrapper in synchronní scénáře.
  • Výpis greedy se nedoporučuje a byl odebrán z knihovny.

Další kroky

Další informace o službě Azure Storage a klientské knihovně pro C++ najdete v následujících zdrojích informací.