Compartir a través de


Guía para solicitudes limitadas en Azure Resource Graph

Cuando se usan datos de Azure Resource Graph mediante programación, es importante tener en cuenta cómo afecta la limitación a los resultados de las consultas. Cambiar la forma en que se solicitan los datos puede ayudarle a usted y a su organización a evitar problemas de limitación y mantener el flujo de datos puntuales sobre los recursos de Azure.

En este artículo se tratan cuatro áreas y patrones relacionados con la creación de consultas en Azure Resource Graph:

  • Comprenda los encabezados de limitación.
  • Agrupación de consultas.
  • Escalonamiento de las consultas.
  • Efecto de la paginación.

Descripción de los encabezados de limitación

Azure Resource Graph asigna un número de cuota para cada usuario en función de una ventana de tiempo. Por ejemplo, un usuario puede enviar como máximo 15 consultas dentro de cada ventana de 5 segundos sin que se vea limitado. El valor de la cuota viene determinado por muchos factores y está sujeto a cambios.

En cada respuesta de consulta, Azure Resource Graph agrega dos encabezados de limitación:

  • x-ms-user-quota-remaining (int): cuota de recursos restante para el usuario. Este valor se asigna al recuento de consultas.
  • x-ms-user-quota-resets-after (hh:mm:ss): la duración del tiempo hasta que se restablece el consumo de cuota de un usuario.

Cuando una entidad de seguridad tiene acceso a más de 10 000 suscripciones dentro del espacio empresarial o grupo de administración ámbito de consulta, la respuesta se limita a las primeras 10 000 suscripciones y el encabezado x-ms-tenant-subscription-limit-hit se devuelve como true.

Para ilustrar cómo funcionan los encabezados, echemos un vistazo a una respuesta de consulta que tiene el encabezado y los valores de x-ms-user-quota-remaining: 10 y x-ms-user-quota-resets-after: 00:00:03.

  • Dentro de los próximos 3 segundos, se pueden enviar como máximo 10 consultas sin que se sufra una limitación.
  • En 3 segundos, los valores de x-ms-user-quota-remaining y x-ms-user-quota-resets-after se restablecerán a 15 y 00:00:05, respectivamente.

Para ver un ejemplo del uso de los encabezados para retroceso en las solicitudes de consulta, consulte el ejemplo de Consulta en paralelo.

Agrupación de consultas

La agrupación de consultas según la suscripción, grupo de recursos o recurso individual es más eficaz que realizar consultas en paralelo. El costo de cuota de una consulta mayor suele ser menor que el costo de cuota de muchas consultas pequeñas y dirigidas. Se recomienda que el tamaño del grupo sea inferior a 300.

  • Ejemplo de un método mal optimizado.

    // 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);
    
    // ...
    }
    
  • Ejemplo de un método de agrupación optimizado.

    // 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);
    
      // ...
    }
    
  • Ejemplo de un enfoque de agrupación optimizado para obtener varios recursos en una 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 sorprendentes

Debido a la forma en que se aplica la limitación, se recomienda que las consultas se escalonen. Por ejemplo, en lugar de enviar 60 consultas al mismo tiempo, escalone las consultas en cuatro ventanas de 5 segundos.

  • Programación de consultas no registrados.

    Recuento de consultas 60 0 0 0
    Intervalo de tiempo (sec) 0-5 5-10 10-15 15-20
  • Programación de consultas escalonadas.

    Recuento de consultas 15 15 15 15
    Intervalo de tiempo (sec) 0-5 5-10 10-15 15-20

El código siguiente es un ejemplo de respetar los encabezados de limitación al consultar 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 en paralelo

Aunque se recomienda la agrupación sobre la paralelización, hay ocasiones en las que las consultas no se pueden agrupar fácilmente. En estos casos, es posible que quiera consultar Azure Resource Graph mediante el envío de varias consultas de forma paralela. En el ejemplo siguiente se muestra cómo retroceso en función de los encabezados de limitación.

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

Paginación

Dado que Azure Resource Graph devuelve un máximo de 1000 entradas en una única respuesta de consulta, es posible que tenga que paginar las consultas para obtener el conjunto de datos completo que desee. Pero algunos clientes de Azure Resource Graph controlan la paginación de forma diferente a otras.

Al usar el SDK de ResourceGraph, debe controlar la paginación pasando el token skip que se devuelve de la respuesta de consulta anterior a la siguiente consulta paginada. Este diseño significa que necesita recopilar resultados de todas las llamadas paginadas y combinarlos al final. En este caso, cada consulta paginada que envíe toma una cuota 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.
}

ARG GET/LIST API

ARG presenta un enfoque alternativo para las llamadas GET y List API del plano de control de Azure existentes que mejoran la escalabilidad y el rendimiento, a la vez que se abordan los problemas de limitación para los clientes de Azure. Actualmente, esta API solo se admite para los recursos en la tabla resources y la tabla computeresources.

La API GET/LIST de ARG está pensada para abordar escenarios en los que se necesita una búsqueda de un único recurso por identificador, o bien se enumeran los recursos con el mismo tipo y dentro de un ámbito determinado (suscripción, grupo de recursos o recurso primario).

Debe tener en cuenta la API GET/LIST de ARG si el servicio entra en una (o varias) de las siguientes categorías:

  • El servicio emite un gran volumen de llamadas GET para recuperar datos de un recurso destinado a una sola suscripción o a un único RG y no requiere lotes de registros de varias suscripciones a través de combinaciones o filtros complejos.

  • El servicio emite un gran volumen de solicitudes GET y corre el riesgo de:

    • Frente a la limitación.
    • Compiten por la cuota de limitación con otros clientes.
    • El servicio puede ser o es propenso a emitir una gran ráfaga de solicitudes GET simultáneas en un breve período de tiempo.
  • El servicio requiere alta disponibilidad y un rendimiento más rápido para las solicitudes GET, para la administración de recursos únicos o la enumeración de una lista de recursos dentro de un ámbito determinado.

  • Necesita la vista completa de las máquinas virtuales y VMSS en uniforme, así como el modo de orquestación Flex.

    Nota:

    ARG GET/LIST API no admite el estado de mantenimiento de la máquina virtual y VMSS y la extensión en ejecución en instanceView. Para más información sobre los límites de la API de ARG GET/LIST, consulte las limitaciones conocidas.

Si el recurso que le interesa, está en la resources tabla o computeresources tabla y se encuentra en una de las categorías anteriores, use la API GET/LIST de ARG.

¿Todavía se está limitando?

Si ha usado las recomendaciones de este artículo, ha probado la solución GET/LIST API de Azure Resource Graph y las consultas de Azure Resource Graph se siguen limitando, póngase en contacto con el equipo de Azure Resource Graph. El equipo proporciona asistencia para Azure Resource Graph, pero no para la Limitación de Microsoft Graph.

Proporcione estos detalles al ponerse en contacto con el equipo de Azure Resource Graph:

  • Sus necesidades de controlador de casos prácticos y empresariales de un límite superior.
  • ¿A cuántos recursos tiene acceso? ¿Cuántos de ellos se devuelven desde una consulta única?
  • ¿Qué tipos de recursos le interesan?
  • ¿Cuál es el modelo de consulta? X consultas por Y segundo, etc.

Pasos siguientes