إرشادات للطلبات المقيدة في Azure Resource Graph

عند إنشاء استخدام برمجي ومتكرر لبيانات Azure Resource Graph، يجب مراعاة كيفية تأثير التقييد على نتائج الاستعلامات. يمكن أن يساعدك تغيير الطريقة التي يتم بها طلب البيانات لك ولمؤسستك على تجنب تقييدك والحفاظ على تدفق البيانات في الوقت المناسب حول موارد Azure.

تتناول هذه المقالة أربعة مجالات وأنماط تتعلق بإنشاء استعلامات في Azure Resource Graph:

  • فهم عناوين التقييد.
  • تجميع الاستعلامات.
  • استعلامات مرحلية.
  • تأثير ترقيم الصفحات.

فهم عناوين التقييد

يخصص Azure Resource Graph رقم الحصة النسبية لكل مستخدم استنادًا إلى نافذة زمنية. على سبيل المثال، يمكن للمستخدم إرسال 15 استعلامًا على الأكثر داخل كل نافذة 5 ثوان دون تقييده. يتم تحديد قيمة الحصة النسبية من قبل العديد من العوامل ومن الجدير بالذكر أنها عرضة للتغيير.

في كل استجابة استعلام، يضيف Azure Resource Graph عنوانين للتقييد:

  • x-ms-user-quota-remaining (int): الحصة النسبية المتبقية للمورد للمستخدم. مخططات القيمة هذه لحساب الاستعلام.
  • x-ms-user-quota-resets-after (hh:mm:ss): المدة الزمنية حتى يتم إعادة تعيين استهلاك الحصة النسبية للمستخدم.

عندما يكون لمدير الأمان حق الوصول إلى أكثر من 10000 اشتراك ضمن نطاق استعلام المستأجر أو مجموعة الإدارة، تقتصر الاستجابة على أول 10000 اشتراك ويتم x-ms-tenant-subscription-limit-hit إرجاع العنوان ك true.

لتوضيح كيفية عمل الرؤوس، دعونا ننظر إلى استجابة استعلام تحتوي على عنوان وقيم x-ms-user-quota-remaining: 10 وx-ms-user-quota-resets-after: 00:00:03.

  • في غضون الثوان الثلاثة التالية، يمكن إرسال 10 استعلامات على الأكثر دون تقييدها.
  • في 3 ثوان، يتم إعادة تعيين قيم x-ms-user-quota-remaining و x-ms-user-quota-resets-after إلى 15 و 00:00:05 على التوالي.

للاطلاع على مثال لاستخدام الرؤوس للتراجع عن طلبات الاستعلام، راجع النموذج في الاستعلام بالتوازي.

تجميع الاستعلامات

يعد تجميع الاستعلامات حسب الاشتراك أو مجموعة الموارد أو المورد الفردي أكثر كفاءة من موازاة الاستعلامات. غالبًا ما تكون تكلفة الحصة النسبية لاستعلام أكبر أقل من تكلفة الحصة النسبية للعديد من الاستعلامات الصغيرة والمستهدفة. يوصى بأن يكون حجم المجموعة أقل من 300.

  • مثال على نهج غير محسن بشكل جيد.

    // 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);
    
    // ...
    }
    
  • مثال على نهج تجميع محسن.

    // 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);
    
      // ...
    }
    
  • مثال على نهج تجميع محسن للحصول على موارد متعددة في استعلام واحد.

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

استعلامات التقسيم المرحلي

نظرًا للطريقة التي يتم بها فرض التقييد، نوصي بأن تكون الاستعلامات متداخلة. على سبيل المثال، بدلا من إرسال 60 استعلارا في نفس الوقت، قم بتقسيم الاستعلامات إلى أربع نوافذ 5 ثوان.

  • جدول استعلام غير علامة.

    عدد الاستعلامات 60 1 0 1
    الفاصل الزمني (ثانية) 0-5 5-10 10-15 15-20
  • جدول الاستعلام المرحلي.

    عدد الاستعلامات 15 15 15 15
    الفاصل الزمني (ثانية) 0-5 5-10 10-15 15-20

التعليمات البرمجية التالية هي مثال على احترام عناوين التقييد عند الاستعلام عن 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);
    }
}

الاستعلام بالتوازي

على الرغم من أن التجميع يوصى به على التوازي، هناك أوقات لا يمكن فيها تجميع الاستعلامات بسهولة. في هذه الحالات، قد تحتاج إلى الاستعلام عن Azure Resource Graph عن طريق إرسال استعلامات متعددة بطريقة متوازية. يوضح المثال التالي كيفية التراجع استنادا إلى عناوين التقييد.

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

فصل الصفحات

نظرا لأن Azure Resource Graph يقوم بإرجاع 1000 إدخال كحد أقصى في استجابة استعلام واحدة، فقد تحتاج إلى ترقيم صفحات الاستعلامات للحصول على مجموعة البيانات الكاملة التي تريدها. ولكن بعض عملاء Azure Resource Graph يتعاملون مع ترقيم الصفحات بشكل مختلف عن الآخرين.

عند استخدام ResourceGraph SDK، تحتاج إلى معالجة ترقيم الصفحات عن طريق تمرير رمز التخطي الذي يتم إرجاعه من استجابة الاستعلام السابقة إلى الاستعلام التالي المرقم. يعني هذا التصميم أنك بحاجة إلى جمع النتائج من جميع المكالمات المرقمة ودمجها معًا في النهاية. في هذه الحالة، يأخذ كل استعلام مرقم ترسله حصة استعلام واحدة.

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

هل ما زلت مقيدا؟

إذا استخدمت توصيات هذه المقالة ولا تزال استعلامات Azure Resource Graph قيد التقييد، فاتصل بفريق Azure Resource Graph. يدعم الفريق Azure Resource Graph ولكنه لا يدعم تقييد Microsoft Graph.

قدم هذه التفاصيل عند الاتصال بفريق Azure Resource Graph:

  • يحتاج برنامج تشغيل حالة الاستخدام والأعمال المحدد إلى حد تقييد أعلى.
  • كم عدد الموارد التي يمكنك الوصول إليها؟ كم عددها التي يتم إرجاعها من استعلام واحد؟
  • ما هي أنواع الموارد التي تهتم بها؟
  • ما هو نمط الاستعلام الخاص بك؟ استعلامات X لكل ثانية Y، وما إلى ذلك.

الخطوات التالية