Testar como seu aplicativo lida com limites de taxa de API GitHub

Tip

Novo para limitação? Saiba o que é limitação de taxa e como lidar com ela.

Visão geral
Meta: Testar como seu aplicativo lida com os limites de taxa da API REST do GitHub
Tempo: 15 minutos
Plugins:RateLimitingPlugin, GenericRandomErrorPlugin, RetryAfterPlugin
Pré-requisitos:Configurar o Proxy de Desenvolvimento

Seu aplicativo faz chamadas à API do GitHub. Ele funciona em seu computador, em seguida, um job de CI, uma grande organização ou um dia agitado faz com que ultrapasse o limite de taxa e começa a falhar. Para testá-lo em relação à API real, você precisará esgotar sua cota de requisições e aguardar até uma hora antes de tentar novamente. O Proxy de Desenvolvimento simula os limites de taxa do GitHub localmente, com um limite e uma janela de tempo que você definir.

Saber o que GitHub retorna

GitHub tem dois tipos de limites de taxa para a API REST.

Os limites de taxa primária limitam quantas solicitações você faz por hora. Por exemplo, 60 para solicitações não autenticadas e 5.000 para solicitações com um token de acesso pessoal. Cada resposta inclui cabeçalhos que mostram onde você está:

Header Meaning
x-ratelimit-limit O número máximo de solicitações por hora
x-ratelimit-remaining O número de solicitações restantes na janela atual
x-ratelimit-reset A hora em que a janela é redefinida, em segundos de época UTC

Quando você excede o limite primário, GitHub retorna 403 ou 429 com x-ratelimit-remaining definido como 0. Não tente novamente até o horário em x-ratelimit-reset.

Os limites de taxa secundários protegem o GitHub contra picos, como muitas solicitações simultâneas ou a criação de muito conteúdo muito rapidamente. Quando você excede um desses limites, GitHub retorna 403 ou 429 com uma mensagem sobre um limite de taxa secundário. Se a resposta tiver um cabeçalho retry-after, aguarde essa quantidade de segundos. Caso contrário, aguarde pelo menos um minuto e aumente o tempo de espera se a solicitação continuar falhando.

GitHub pode proibir integrações que continuam enviando solicitações enquanto estão sujeitas ao limite de taxa. Para obter mais informações, consulte Os limites de taxa para a API REST na documentação do GitHub.

Simular o limite de taxa primária

Use o plugin RateLimitingPlugin para contar solicitações e retornar os cabeçalhos de limite de requisições do GitHub. Para testar sem esperar uma hora, use um pequeno limite e uma janela curta.

Arquivo: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "RetryAfterPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll"
    },
    {
      "name": "RateLimitingPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "githubRateLimit"
    }
  ],
  "urlsToWatch": [
    "https://api.github.com/*"
  ],
  "githubRateLimit": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/ratelimitingplugin.schema.json",
    "headerLimit": "x-ratelimit-limit",
    "headerRemaining": "x-ratelimit-remaining",
    "headerReset": "x-ratelimit-reset",
    "resetFormat": "UtcEpochSeconds",
    "costPerRequest": 1,
    "rateLimit": 5,
    "resetTimeWindowSeconds": 60,
    "warningThresholdPercent": 0,
    "whenLimitExceeded": "Custom",
    "customResponseFile": "github-rate-limit-exceeded.json"
  }
}

Caution

Adicione o RetryAfterPlugin antes do RateLimitingPlugin em seu arquivo de configuração. Se você adicioná-la depois, o RateLimitingPlugin manipula a solicitação antes que o RetryAfterPlugin possa verificá-la.

No arquivo de resposta personalizado, defina a resposta que o GitHub retorna quando você excede o limite primário de taxa.

Arquivo: github-rate-limit-exceeded.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/ratelimitingplugin.customresponsefile.schema.json",
  "statusCode": 429,
  "headers": [
    {
      "name": "content-type",
      "value": "application/json; charset=utf-8"
    }
  ],
  "body": {
    "message": "API rate limit exceeded for user ID 1.",
    "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api"
  }
}

Inicie o Proxy de Desenvolvimento e execute seu aplicativo.

devproxy --config-file devproxyrc.json

O Proxy de Desenvolvimento encaminha as cinco primeiras solicitações em cada minuto para GitHub e define os cabeçalhos x-ratelimit-* nas respostas. Na 6ª solicitação em diante, o Dev Proxy retorna a resposta do limite de taxa com x-ratelimit-remaining definido como 0 e x-ratelimit-reset definido como o final da janela. Se o aplicativo chamar a API novamente antes que a janela seja redefinida, o RetryAfterPlugin reporta e restringe a taxa da solicitação.

Verifique se seu aplicativo:

  • Detecta x-ratelimit-remaining e reduz a velocidade antes de chegar a 0.
  • Para de chamar a API após uma resposta de limite de taxa e aguarda até que x-ratelimit-reset.
  • Informa ao usuário o que está acontecendo, por exemplo"GitHub limite de taxa atingido, repetindo às 14:05", em vez de falhar silenciosamente.

Note

GitHub retorna 403 ou 429 quando você excede um limite de taxa. Para testar se o aplicativo também manipula 403 , altere statusCode para 403. O RetryAfterPlugin apenas controla as respostas 429, portanto, ele não relata novas tentativas antecipadas após um 403.

Tip

O Proxy de Desenvolvimento encaminha solicitações para GitHub até que o limite simulado seja atingido. Essas solicitações também consomem o seu limite real de taxa do GitHub.

Simular limites secundários de requisições

Os limites de taxa secundários vêm em rajadas e incluem um cabeçalho retry-after. Use o GenericRandomErrorPlugin para devolvê-los aleatoriamente.

Arquivo: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "RetryAfterPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll"
    },
    {
      "name": "GenericRandomErrorPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "githubSecondaryRateLimit"
    }
  ],
  "urlsToWatch": [
    "https://api.github.com/*"
  ],
  "githubSecondaryRateLimit": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.schema.json",
    "errorsFile": "github-secondary-rate-limit.json",
    "rate": 50,
    "retryAfterInSeconds": 60
  }
}

Arquivo: github-secondary-rate-limit.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.github.com/*"
      },
      "responses": [
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            },
            {
              "name": "retry-after",
              "value": "@dynamic"
            }
          ],
          "body": {
            "message": "You have exceeded a secondary rate limit. Please wait a few minutes before you try again.",
            "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits"
          }
        }
      ]
    }
  ]
}

Inicie o Proxy de Desenvolvimento e execute seu aplicativo. Verifique se o aplicativo aguarda o número de segundos indicado no cabeçalho retry-after antes de chamar a API novamente. Se não, o RetryAfterPlugin relata isso.

Se você usar o Octokit com o plug-in de limitação, verifique se seus manipuladores onRateLimit e onSecondaryRateLimit são executados e se eles retornam o resultado esperado.

Próxima etapa

Saiba mais sobre o RateLimitingPlugin.

Consulte também