Delen via


Richtlijnen voor beperkte aanvragen in Azure Resource Graph

Wanneer u programmatisch Azure Resource Graph-gegevens gebruikt, is het belangrijk om te overwegen welke invloed de limitering van verwerkingscapaciteit heeft op de resultaten van de query's. Als u de manier wijzigt waarop gegevens worden aangevraagd, kunnen u en uw organisatie problemen met beperkingen voorkomen en de stroom van tijdige gegevens over uw Azure-resources behouden.

In dit artikel worden vier gebieden en patronen behandeld die betrekking hebben op het maken van query's in Azure Resource Graph:

  • Informatie over beperkingsheaders.
  • Query's groeperen.
  • Verspringende query's.
  • Het effect van paginering.

Informatie over headers voor bandbreedtebeperking

Azure Resource Graph wijst elke gebruiker een quotumnummer toe op basis van een tijdvenster. Een gebruiker kan bijvoorbeeld maximaal 15 query's verzenden binnen elk venster van 5 seconden zonder te worden beperkt. De quotumwaarde wordt bepaald door veel factoren en kan worden gewijzigd.

In elk queryantwoord voegt Azure Resource Graph twee beperkingsheaders toe:

  • x-ms-user-quota-remaining (int): Het resterende resourcequotum voor de gebruiker. Deze waarde wordt toegewezen aan het aantal query's.
  • x-ms-user-quota-resets-after (uu:mm:ss): de tijdsduur totdat het quotumverbruik van een gebruiker opnieuw wordt ingesteld.

Wanneer een beveiligingsprincipaal toegang heeft tot meer dan 10.000 abonnementen binnen het querybereik van de tenant of beheergroep, is het antwoord beperkt tot de eerste 10.000 abonnementen en wordt de x-ms-tenant-subscription-limit-hit header geretourneerd als true.

Laten we eens kijken naar een queryantwoord met de koptekst en waarden van x-ms-user-quota-remaining: 10 en x-ms-user-quota-resets-after: 00:00:03om te laten zien hoe de headers werken.

  • Binnen de volgende 3 seconden kunnen maximaal 10 query's worden verzonden zonder te worden beperkt.
  • In 3 seconden worden de waarden van x-ms-user-quota-remaining en x-ms-user-quota-resets-after respectievelijk opnieuw ingesteld 15 op en 00:00:05 respectievelijk.

Als u een voorbeeld wilt zien van het gebruik van de headers voor uitstel van queryaanvragen, raadpleegt u het voorbeeld in Query parallel.

Groeperen van query's

Het groeperen van query's per abonnement, resourcegroep of afzonderlijke resource is efficiënter dan het parallelliseren van query's. De quotumkosten van een grotere query zijn vaak lager dan de quotumkosten van veel kleine en gerichte query's. De groepsgrootte wordt aanbevolen om kleiner dan 300 te zijn.

  • Voorbeeld van een slecht geoptimaliseerde benadering.

    // NOT RECOMMENDED
    var header = /* your request header */
    var subscriptionIds = /* A big list of subscriptionIds */
    
    foreach (var subscriptionId in subscriptionIds)
    {
        var userQueryRequest = new QueryRequest(
            subscriptions: new[] { subscriptionId },
            query: "Resources | project name, type");
    
        var azureOperationResponse = await this.resourceGraphClient
            .ResourcesWithHttpMessagesAsync(userQueryRequest, header)
            .ConfigureAwait(false);
    
    // ...
    }
    
  • Voorbeeld van een geoptimaliseerde groeperingsmethode.

    // RECOMMENDED
    var header = /* your request header */
    var subscriptionIds = /* A big list of subscriptionIds */
    
    const int groupSize = 100;
    for (var i = 0; i <= subscriptionIds.Count / groupSize; ++i)
    {
        var currSubscriptionGroup = subscriptionIds.Skip(i * groupSize).Take(groupSize).ToList();
        var userQueryRequest = new QueryRequest(
            subscriptions: currSubscriptionGroup,
            query: "Resources | project name, type");
    
        var azureOperationResponse = await this.resourceGraphClient
            .ResourcesWithHttpMessagesAsync(userQueryRequest, header)
            .ConfigureAwait(false);
    
      // ...
    }
    
  • Voorbeeld van een geoptimaliseerde groeperingsmethode voor het verkrijgen van meerdere resources in één query.

    Resources | where id in~ ({resourceIdGroup}) | project name, type
    
    // RECOMMENDED
    var header = /* your request header */
    var resourceIds = /* A big list of resourceIds */
    
    const int groupSize = 100;
    for (var i = 0; i <= resourceIds.Count / groupSize; ++i)
    {
        var resourceIdGroup = string.Join(",",
            resourceIds.Skip(i * groupSize).Take(groupSize).Select(id => string.Format("'{0}'", id)));
        var userQueryRequest = new QueryRequest(
            subscriptions: subscriptionList,
            query: $"Resources | where id in~ ({resourceIdGroup}) | project name, type");
    
        var azureOperationResponse = await this.resourceGraphClient
            .ResourcesWithHttpMessagesAsync(userQueryRequest, header)
            .ConfigureAwait(false);
    
      // ...
    }
    

Query's spreiden

Vanwege de manier waarop beperking wordt afgedwongen, wordt u aangeraden query's te spreiden. In plaats van bijvoorbeeld 60 query's tegelijk te verzenden, kunt u de query's in vier vensters van 5 seconden verdelen.

  • Niet-getaggered queryschema.

    Aantal query's 60 0 0 0
    Tijdsinterval (sec) 0-5 5-10 10-15 15-20
  • Gefaseerde queryplanning.

    Aantal query's 15 15 15 15
    Tijdsinterval (sec) 0-5 5-10 10-15 15-20

De volgende code is een voorbeeld van het respecteren van beperkingsheaders bij het uitvoeren van query's op Azure Resource Graph.

while (/* Need to query more? */)
{
    var userQueryRequest = /* ... */
    // Send post request to Azure Resource Graph
    var azureOperationResponse = await this.resourceGraphClient
        .ResourcesWithHttpMessagesAsync(userQueryRequest, header)
        .ConfigureAwait(false);

    var responseHeaders = azureOperationResponse.response.Headers;
    int remainingQuota = /* read and parse x-ms-user-quota-remaining from responseHeaders */
    TimeSpan resetAfter = /* read and parse x-ms-user-quota-resets-after from responseHeaders */
    if (remainingQuota == 0)
    {
        // Need to wait until new quota is allocated
        await Task.Delay(resetAfter).ConfigureAwait(false);
    }
}

Query parallel uitvoeren

Hoewel groepering wordt aanbevolen voor parallelle uitvoering, zijn er situaties waarin query's niet eenvoudig kunnen worden gegroepeerd. In dergelijke gevallen wilt u mogelijk query's uitvoeren op Azure Resource Graph door meerdere query's parallel te verzenden. In het volgende voorbeeld ziet u hoe u uitstelt op basis van beperkingsheaders.

IEnumerable<IEnumerable<string>> queryGroup = /* Groups of queries  */
// Run groups in parallel.
await Task.WhenAll(queryGroup.Select(ExecuteQueries)).ConfigureAwait(false);

async Task ExecuteQueries(IEnumerable<string> queries)
{
    foreach (var query in queries)
    {
        var userQueryRequest = new QueryRequest(
            subscriptions: subscriptionList,
            query: query);
        // Send post request to Azure Resource Graph.
        var azureOperationResponse = await this.resourceGraphClient
            .ResourcesWithHttpMessagesAsync(userQueryRequest, header)
            .ConfigureAwait(false);

        var responseHeaders = azureOperationResponse.response.Headers;
        int remainingQuota = /* read and parse x-ms-user-quota-remaining from responseHeaders */
        TimeSpan resetAfter = /* read and parse x-ms-user-quota-resets-after from responseHeaders */
        if (remainingQuota == 0)
        {
            // Delay by a random period to avoid bursting when the quota is reset.
            var delay = (new Random()).Next(1, 5) * resetAfter;
            await Task.Delay(delay).ConfigureAwait(false);
        }
    }
}

Paginering

Omdat Azure Resource Graph maximaal 1000 vermeldingen retourneert in één queryantwoord, moet u mogelijk uw query's pagineren om de gewenste volledige gegevensset op te halen. Maar sommige Azure Resource Graph-clients verwerken paginering anders dan andere.

Wanneer u ResourceGraph SDK gebruikt, moet u paginering afhandelen door het skip-token door te geven dat wordt geretourneerd vanuit het vorige queryantwoord naar de volgende gepagineerde query. Dit ontwerp betekent dat u resultaten van alle gepagineerde oproepen moet verzamelen en deze aan het einde moet combineren. In dit geval heeft elke gepagineerde query die u verzendt één queryquotum.

var results = new List<object>();
var queryRequest = new QueryRequest(
  subscriptions: new[] { mySubscriptionId },
  query: "Resources | project id, name, type");
var azureOperationResponse = await this.resourceGraphClient
  .ResourcesWithHttpMessagesAsync(queryRequest, header)
  .ConfigureAwait(false);
while (!string.IsNullOrEmpty(azureOperationResponse.Body.SkipToken))
{
  queryRequest.Options ??= new QueryRequestOptions();
  queryRequest.Options.SkipToken = azureOperationResponse.Body.SkipToken;
  var azureOperationResponse = await this.resourceGraphClient
      .ResourcesWithHttpMessagesAsync(queryRequest, header)
      .ConfigureAwait(false);
  results.Add(azureOperationResponse.Body.Data.Rows);

// Inspect throttling headers in query response and delay the next call if needed.
}

ARG GET/LIST-API

ARG introduceert een alternatieve benadering voor de bestaande Azure besturingsvlak GET- en List-API-aanroepen die de schaalbaarheid en prestaties verbeteren, terwijl beperkingsproblemen voor Azure-klanten worden aangepakt. Deze API wordt momenteel alleen ondersteund voor resources in de resources tabel en computeresources tabel.

De ARG GET/LIST-API is bedoeld voor het oplossen van scenario's waarbij u één resource op basis van id nodig hebt, of u vermeldt resources onder hetzelfde type en binnen een bepaald bereik (abonnement, resourcegroep of bovenliggende resource).

Overweeg de ARG GET/LIST-API als uw service in een (of veel) van de volgende categorieën valt:

  • Uw service geeft een groot aantal GET-aanroepen uit om gegevens op te halen voor een resource die is gericht op één abonnement of één RG en vereist geen batches van records uit meerdere abonnementen via complexe filters of joins.

  • Uw service geeft een groot aantal GET-aanvragen uit en loopt het risico op:

    • Te maken hebben met beperking.
    • Concurreren voor beperkingsquotum met andere klanten.
    • Uw service is of is gevoelig voor het uitgeven van een grote burst van gelijktijdige GET-aanvragen binnen een korte periode.
  • Uw service vereist hoge beschikbaarheid en snellere prestaties voor GET-aanvragen, voor één resourcebeheer of opsomming van een lijst met resources binnen een bepaald bereik.

  • U hebt volledige instantieview van VM's en VMSS-VM's in de uniforme en Flex-orkestratiemodus nodig.

    Opmerking

    ARG GET/LIST API biedt geen ondersteuning voor de VM en VMSS Gezondheidsstatus en de status van actieve extensies in de InstanceView. Zie de bekende beperkingen voor meer informatie over de LIMIETen voor ARG GET/LIST API.

Als de resource waarin u geïnteresseerd bent, zich in de resources tabel of computeresources tabel bevindt en deze in een van de bovenstaande categorieën valt, gebruikt u de ARG GET/LIST-API.

Nog steeds beperkt?

Als u de aanbevelingen van dit artikel hebt gebruikt, hebt u de Azure Resource Graph GET/LIST API-oplossing geprobeerd en worden uw Azure Resource Graph-query's nog steeds beperkt, neemt u contact op met het Azure Resource Graph-team. Het team ondersteunt Azure Resource Graph, maar biedt geen ondersteuning voor Microsoft Graph-beperking.

Geef deze gegevens op wanneer u contact op neemt met het Azure Resource Graph-team:

  • Uw specifieke use-case- en business driver-behoeften voor een hogere beperkingslimiet.
  • Tot hoeveel resources hebt u toegang? Hoeveel van deze query's worden geretourneerd vanuit één query?
  • In welke typen resources bent u geïnteresseerd?
  • Wat is uw querypatroon? X-query's per Y seconden, enzovoort.

Volgende stappen