Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Ao usar dados do Azure Resource Graph programaticamente, é importante considerar como a limitação afeta os resultados das consultas. Alterar a forma como os dados são solicitados pode ajudar você e sua organização a evitarem problemas de limitação e manterem o fluxo de dados oportunos sobre seus recursos do Azure.
Este artigo aborda quatro áreas e padrões relacionados à criação de consultas no Azure Resource Graph:
- Entenda os cabeçalhos de limitação.
- Como agrupar consultas.
- Consultas de escalonamento.
- O efeito da paginação.
Noções básicas sobre os cabeçalhos de limitação
O Azure Resource Graph aloca um número de cota para cada usuário com base em uma janela de tempo. Por exemplo, um usuário pode enviar no máximo 15 consultas dentro de cada janela de 5 segundos sem ser limitado. O valor da cota é determinado por muitos fatores e está sujeito a mudanças.
Em cada resposta de consulta, o Azure Resource Graph adiciona dois cabeçalhos de limitação:
-
x-ms-user-quota-remaining(int): a cota de recurso restante para o usuário. Esse valor é mapeado para a contagem de consultas. -
x-ms-user-quota-resets-after(hh:mm:ss): a duração de tempo até que o consumo da cota do usuário seja redefinido.
Quando uma entidade de segurança tem acesso a mais de 10 mil assinaturas no escopo de consulta do locatário ou do grupo de gerenciamento, a resposta é limitada às primeiras 10 mil assinaturas e o cabeçalho x-ms-tenant-subscription-limit-hit retorna como true.
Para ilustrar como os cabeçalhos funcionam, examinaremos a resposta de uma consulta que tem o cabeçalho e os valores de x-ms-user-quota-remaining: 10 e x-ms-user-quota-resets-after: 00:00:03.
- Nos próximos três segundos, no máximo dez consultas poderão ser enviadas sem serem limitadas.
- Em 3 segundos, os valores de
x-ms-user-quota-remainingex-ms-user-quota-resets-afterserão redefinidos para15e00:00:05, respectivamente.
Para ver um exemplo de como usar os cabeçalhos para retirada em solicitações de consulta, confira a amostra em Consulta em paralelo.
Agrupar consultas
O agrupamento de consultas por assinatura, grupo de recursos ou recurso individual é mais eficiente do que paralelizar consultas. O custo de cota de uma consulta maior geralmente é menor do que o custo de cota de muitas consultas pequenas e direcionadas. É recomendável que o tamanho do grupo seja inferior a 300.
Exemplo de uma abordagem com otimização insuficiente.
// 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); // ... }Exemplo de uma abordagem de agrupamento otimizada.
// 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); // ... }Exemplo de uma abordagem de agrupamento otimizada para obter vários recursos em uma consulta.
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); // ... }
Consultas de escalonamento
Devido à maneira como a limitação é imposta, recomendamos que as consultas sejam escalonadas. Por exemplo, em vez de enviar 60 consultas ao mesmo tempo, escalone as consultas em quatro janelas de cinco segundos.
Programação de consultas não escalonada.
Contagem de consultas 60 0 0 0 Intervalo de tempo (s) 0 a 5 5-10 10-15 15–20 Programação de consultas escalonada.
Contagem de consultas 15 15 15 15 Intervalo de tempo (s) 0 a 5 5-10 10-15 15–20
O código a seguir é um exemplo de como respeitar os cabeçalhos de limitação ao consultar o 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);
}
}
Consulta em paralelo
Embora o agrupamento seja recomendado em detrimento da paralelização, há ocasiões em que as consultas não podem ser agrupadas facilmente. Nesses casos, você talvez queira consultar o Azure Resource Graph enviando várias consultas em paralelo. O exemplo a seguir mostra como fazer uma retirada baseada em cabeçalhos de limitação.
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);
}
}
}
Paginação
Como o Azure Resource Graph retorna um máximo de 1.000 entradas em uma única resposta de consulta, talvez você precise paginar suas consultas para obter o conjunto de dados completo que você quer. Mas alguns clientes do Azure Resource Graph lidam com a paginação de uma maneira diferente.
Ao usar o SDK do ResourceGraph, é preciso lidar com a paginação passando o token de omissão retornado na resposta da consulta anterior para a próxima consulta paginada. Isso significa que é preciso coletar resultados de todas as chamadas paginadas e combiná-las no final. Nesse caso, cada consulta paginada que você envia consome uma cota de consulta.
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.
}
Diferenciar entre solicitações de limitação para o ARG e o ARM
Ao usar a API GET/LIST do ARG, você poderá encontrar erros de limite em resposta às suas solicitações. É importante identificar a origem da limitação, pois ela pode ocorrer em dois níveis:
- Limitação da API do ARG: limites aplicados pelo Azure Resource Graph.
- Limitação do ARM: limites impostos pelo Azure Resource Manager.
Saber qual camada está causando a limitação ajuda você a aplicar a estratégia de mitigação correta.
Este é um exemplo de erro de limitação do ARG:
{
"error": {
"code": "RateLimiting",
"message": "Please provide below info when asking for support: timestamp = 2025-10-16T18:06:54.4721412Z, correlationId = a90921ec-4649-431a-9c92-7a4394a15883.",
"details": [
{
"code": "RateLimiting",
"message": "Client application has been throttled and should not attempt to repeat the request until an amount of time has elapsed. Please see https://aka.ms/resourcegraph-throttling for help."
}
]
}
}
Por outro lado, este é um exemplo de erro de limitação do ARM:
Observação
Os limites do ARM são limites rígidos que não podem ser aumentados.
<value>
Number of 'read' requests for subscription '{1}' actor '{2}' exceeded. Please try again after '{3}' seconds after additional tokens are available. Refer to https://aka.ms/arm-throttling for additional information.
</value>
Se você receber um erro de limitação do ARM, recomendamos que você consulte as recomendações do ARM para entender como os limites do ARM são impostos.
API GET/LIST do ARG
O ARG está introduzindo uma abordagem alternativa às chamadas de API GET e List do painel de controle do Azure que melhoram a escalabilidade e o desempenho, além de resolver problemas de limitação para clientes do Azure. Atualmente, essa API tem suporte apenas para recursos na tabela resources e na tabela computeresources.
A API GET/LIST do ARG destina-se a abordar cenários em que você precisa de uma pesquisa de um único recurso por ID ou está listando recursos no mesmo tipo e dentro de um determinado escopo (assinatura, grupo de recursos ou recurso pai).
Você deve considerar a API GET/LIST do ARG se o serviço se enquadrar em uma (ou muitas) das seguintes categorias:
Seu serviço está emitindo um grande volume de chamadas GET para recuperar dados de um recurso direcionado a uma única assinatura ou a um único RG e não requer lotes de registros de várias assinaturas por meio de filtragem ou junções complexas.
Seu serviço emite um grande volume de solicitações GET e corre o risco de:
- Enfrentando limitação.
- Competindo pela cota de limitação com outros clientes.
- Seu serviço pode ser ou está propenso a emitir um grande volume de solicitações GET simultâneas em um curto espaço de tempo.
Seu serviço requer alta disponibilidade e desempenho mais rápido para solicitações GET, para gerenciamento de recursos únicos ou enumeração de uma lista de recursos em um determinado escopo.
Você precisa de uma visualização completa das VMs e VMs do VMSS em modo de orquestração Uniforme e Flex.
Observação
A API GET/LIST do ARG não dá suporte ao Status de Integridade de VMs e VMs do VMSS e ao status de execução da extensão na instanceView. Para saber mais sobre os limites da API GET/LIST do ARG, consulte as limitações conhecidas.
Se o recurso de seu interesse estiver na resources tabela ou na computeresources tabela, e ele se enquadrar em uma das categorias acima, use a API GET/LIST ARG.
Continua sendo limitado?
Se você seguiu as recomendações desse artigo, tentou a solução de API GET/LIST do Azure Resource Graph e suas consultas ao Azure Resource Graph ainda estão sendo limitadas, entre em contato com a equipe do Azure Resource Graph. A equipe dá suporte ao Azure Resource Graph, mas não dá suporte à limitação do Microsoft Graph.
Forneça os seguintes detalhes quando entrar em contato com a equipe do Azure Resource Graph:
- Seu caso de uso específico e o fator comercial precisam de um limite de limitação mais alto.
- A quantos recursos você tem acesso? Quantos deles são retornados por uma única consulta?
- Em quais tipos de recursos você está interessado?
- Qual é seu padrão de consulta? X consultas por Y segundos e assim por diante.
Próximas etapas
- Consulte a linguagem em uso em Consultas iniciais.
- Consulte os usos avançados em Consultas avançadas.
- Saiba mais sobre como explorar os recursos.