Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
При программном использовании данных 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): длительность до сброса квоты пользователя.
Если субъект безопасности имеет доступ к более чем 10 000 подписок в области запроса клиента или группы управления, ответ ограничен первым 10 000 подписками, а x-ms-tenant-subscription-limit-hit
заголовок возвращается как true
.
Чтобы продемонстрировать работу этих заголовков, давайте рассмотрим ответ на запрос со следующими значениями заголовков: x-ms-user-quota-remaining: 10
и x-ms-user-quota-resets-after: 00:00:03
.
- В течение следующих 3 секунд можно отправлять не более 10 запросов без регулирования.
- Через 3 секунды значения
x-ms-user-quota-remaining
и сбрасываются соответственно15
00:00:05
.x-ms-user-quota-resets-after
Чтобы просмотреть пример использования заголовков для возврата запросов, ознакомьтесь с примером в запросе параллельно.
Группирование запросов
Группирование запросов по подпискам, группам ресурсов или конкретному ресурсу работает более эффективно, чем параллельное выполнение. Более крупный запрос часто меньше влияет на квоту, чем множество мелких и конкретных запросов. Мы рекомендуем создавать группы размером не более 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: "Resources | 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 0 0 0 Интервал времени (с) 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 обрабатывают разбиение на страницы по-разному, чем другие.
При использовании пакета SDK ResourceGraph для поддержки разбиения на страницы нужно передавать в запросе маркер пропуска, полученный в ответе на предыдущий запрос. Такой механизм означает, что вам придется самостоятельно объединять результаты из всех вызовов, получающих страницы одного набора. В этом случае каждый отправляемый запрос с разбивкой на страницы принимает одну квоту запроса.
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:
- Подробности о вашем варианте использования и бизнес-обоснование для повышения предела регулирования.
- К какому объему ресурсов у вас есть доступ? Сколько из них возвращаются из одного запроса?
- Какие типы ресурсов вас интересуют?
- Какой шаблон запросов вы используете? Данные о числе выполненных запросов в секунду и т. п.
Следующие шаги
- См. описание используемого языка в статье Примеры запросов к Resource Graph для начинающих.
- Описание расширенных вариантов использования см. в статье Примеры расширенных запросов к Resource Graph.
- Узнайте больше о том, как изучать ресурсы.