Azure Kaynak Grafı'da kısıtlanmış istekler için yönergeler

Azure Kaynak Grafı verilerinin program aracılığıyla ve sık kullanımı oluşturulurken azaltmanın sorguların sonuçlarını nasıl etkilediği konusunda dikkate alınması gerekir. Verilerin isteniş biçimini değiştirmek, sizin ve kuruluşunuzun kısıtlanmasını önlemenize ve Azure kaynaklarınız hakkındaki zamanında veri akışını sürdürmenize yardımcı olabilir.

Bu makale, Azure Kaynak Grafı'de sorgu oluşturmayla ilgili dört alanı ve deseni kapsar:

  • Azaltma üst bilgilerini anlama.
  • Sorguları gruplandırma.
  • Aşamalı sorgular.
  • Sayfalandırmanın etkisi.

Azaltma üst bilgilerini anlama

Azure Kaynak Grafı, bir zaman penceresine göre her kullanıcı için bir kota sayısı ayırır. Örneğin, bir kullanıcı kısıtlanmadan her 5 saniyede bir en fazla 15 sorgu gönderebilir. Kota değeri birçok faktör tarafından belirlenir ve değiştirilebilir.

Azure Kaynak Grafı her sorgu yanıtında iki azaltma üst bilgisi ekler:

  • x-ms-user-quota-remaining (int): Kullanıcı için kalan kaynak kotası. Bu değer sorgu sayısına eşler.
  • x-ms-user-quota-resets-after (ss:dd:ss): Kullanıcının kota tüketimi sıfırlanıncaya kadar olan süre.

Bir güvenlik sorumlusunun kiracı veya yönetim grubu sorgu kapsamındaki 10.000'den fazla aboneliğe erişimi olduğunda, yanıt ilk 10.000 abonelikle sınırlıdır ve x-ms-tenant-subscription-limit-hit üst bilgi olarak truedöndürülür.

Üst bilgilerin nasıl çalıştığını göstermek için ve üst bilgisine ve değerlerine sahip bir sorgu yanıtına x-ms-user-quota-remaining: 10x-ms-user-quota-resets-after: 00:00:03bakalım.

  • Sonraki 3 saniye içinde, kısıtlanmadan en fazla 10 sorgu gönderilebilir.
  • 3 saniye içinde ve x-ms-user-quota-resets-after değerleri x-ms-user-quota-remaining sırasıyla ve 00:00:05 olarak 15 sıfırlanır.

Sorgu isteklerinde geri çekilmek için üst bilgileri kullanma örneğini görmek için Bkz. Paralel sorgudaki örneğe.

Sorguları gruplandırma

Sorguları aboneliğe, kaynak grubuna veya tek tek kaynağa göre gruplandırma, sorguları paralelleştirmekten daha verimlidir. Daha büyük bir sorgunun kota maliyeti genellikle çok sayıda küçük ve hedeflenen sorgunun kota maliyetinden daha düşüktür. Grup boyutunun 300'den küçük olması önerilir.

  • Kötü iyileştirilmiş bir yaklaşım örneği.

    // 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: "Resoures | project name, type");
    
        var azureOperationResponse = await this.resourceGraphClient
            .ResourcesWithHttpMessagesAsync(userQueryRequest, header)
            .ConfigureAwait(false);
    
    // ...
    }
    
  • İyileştirilmiş gruplandırma yaklaşımı örneği.

    // 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);
    
      // ...
    }
    
  • Bir sorguda birden çok kaynak almak için iyileştirilmiş bir gruplandırma yaklaşımı örneği.

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

Sorguları kademelendirme

Azaltmanın zorlanma şekli nedeniyle sorguların kademelendirilmesi önerilir. Örneğin, aynı anda 60 sorgu göndermek yerine sorguları dört adet 5 saniyelik pencereye dönüştürebilirsiniz.

  • Aşamalı olmayan sorgu zamanlaması.

    Sorgu Sayısı 60 0 0 0
    Zaman Aralığı (sn) 0-5 5-10 10-15 15-20
  • Aşamalı sorgu zamanlaması.

    Sorgu Sayısı 15 15 15 15
    Zaman Aralığı (sn) 0-5 5-10 10-15 15-20

Aşağıdaki kod, Azure Kaynak Grafı sorgulanırken azaltma üst bilgilerine saygı gösteren bir örnektir.

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

Paralel sorgu

Paralelleştirme üzerinde gruplandırma önerilmesine rağmen sorguların kolayca gruplandırılabildiği zamanlar vardır. Bu gibi durumlarda, paralel bir şekilde birden çok sorgu göndererek Azure Kaynak Grafı sorgulamak isteyebilirsiniz. Aşağıdaki örnekte, azaltma üst bilgilerine göre geri çekilme işlemi gösterilmektedir.

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

Sayfalandırma

Azure Kaynak Grafı tek bir sorgu yanıtında en fazla 1.000 girdi döndürdüğünden, istediğiniz veri kümesinin tamamını almak için sorgularınızı sayfalandırmanız gerekebilir. Ancak bazı Azure Kaynak Grafı istemcileri sayfalandırmayı diğerlerinden farklı işler.

ResourceGraph SDK'sını kullanırken, önceki sorgu yanıtından döndürülen atlama belirtecini sonraki sayfalandırılmış sorguya geçirerek sayfalandırmayı işlemeniz gerekir. Bu tasarım, tüm sayfalandırılmış çağrılardan sonuç toplamanız ve bunları sonunda birleştirmeniz gerektiği anlamına gelir. Bu durumda, gönderdiğiniz her sayfalandırılmış sorgu bir sorgu kotası alır.

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

Hala kısıtlanıyor musun?

Bu makalenin önerilerini kullandıysanız ve Azure Kaynak Grafı sorgularınız hala kısıtlanıyorsa Azure Kaynak Grafı ekibine başvurun. Ekip Azure Kaynak Grafı'ı destekler ancak Microsoft Graph azaltmayı desteklemez.

Azure Kaynak Grafı ekibine başvurarak şu ayrıntıları sağlayın:

  • Kullanım örneğiniz ve iş sürücünüz daha yüksek bir azaltma sınırına ihtiyaç duyar.
  • Kaç kaynağa erişiminiz var? Tek bir sorgudan kaç tane döndürülür?
  • Ne tür kaynaklarla ilgileniyorsunuz?
  • Sorgu deseniniz nedir? Y saniye başına X sorguları vb.

Sonraki adımlar