Limite de taxa da API do GitHub ultrapassado: o que significa e como lidar com isso

O GitHub limita quantos pedidos de API REST a tua aplicação pode enviar. Quando ultrapassa um limite, o GitHub recusa os seus pedidos com um estado 403 ou 429 até o limite ser reiniciado ou o tempo de espera passar. O GitHub tem dois tipos de limites: um limite primário para solicitações por hora e limites secundários que protegem contra rajadas. Se a tua aplicação continuar a enviar pedidos enquanto está limitada pela taxa, o GitHub pode banir a tua integração. Para mais informações, consulte Limites de taxa para a API REST.

Como são os limites de taxa de pedidos do GitHub

Limit Value Quando o reveres
Primária, não autenticada 60 solicitações por hora, por endereço IP 403 ou 429, e x-ratelimit-remaining é 0
Token de acesso primário e pessoal 5.000 solicitações por hora Mesmo que acima
Primário, GITHUB_TOKEN no GitHub Actions 1.000 solicitações por hora, por repositório Mesmo que acima
Secundária Por exemplo, não mais de 100 pedidos concorrentes, 900 pontos por minuto para endpoints REST e cerca de 80 pedidos geradores de conteúdo por minuto 403 ou 429 com uma mensagem de erro. retry-after pode estar presente.

O GitHub pode alterar limites secundários sem aviso, e não há forma de verificar quão perto estás deles.

Cada resposta inclui cabeçalhos que indicam qual é a sua posição em relação ao limite primário:

Header O que isto lhe diz
x-ratelimit-limit O número máximo de pedidos que pode enviar por hora
x-ratelimit-remaining Quantas solicitações te restam na janela atual
x-ratelimit-used Quantas solicitações enviaste na janela atual
x-ratelimit-reset Quando a janela reinicia, em segundos da época UTC
x-ratelimit-resource Em relação a que limite o pedido é contabilizado

Como lidar com um limite de taxa de pedidos no GitHub

  1. Distingue um limite de pedidos de um erro de permissão. O GitHub também retorna 403 quando o seu token não tem acesso. Se a resposta não tiver retry-after, x-ratelimit-remaining não 0é, e a mensagem não mencionar um limite de pedidos, é um problema de permissões. Não tente novamente.
  2. Segue retry-after primeiro. Se o cabeçalho estiver presente, espere esse número de segundos.
  3. Caso contrário, espera pelo reset. Se x-ratelimit-remaining for 0, não volte a tentar até à hora indicada em x-ratelimit-reset.
  4. Caso contrário, espera pelo menos 1 minuto. Para um limite secundário sem nenhum dos cabeçalhos, o GitHub pede que espere pelo menos 1 minuto e que espere mais tempo após cada tentativa falhada. Pára após um número definido de tentativas e gera um erro.
  5. Abranda antes de esgotares o teu limite. Usa x-ratelimit-remaining e x-ratelimit-reset para controlar os teus pedidos. Não construas lógica em torno de uma contagem exata restante, porque o GitHub pode alterar limites. Os x-ratelimit-* cabeçalhos são a fonte da verdade, não o GET /rate_limit endpoint.
async function githubWaitMs(response, attempt) {
  if (response.status !== 403 && response.status !== 429) {
    return null;
  }
  const retryAfter = response.headers.get('retry-after');
  if (retryAfter) {
    return Number(retryAfter) * 1000;
  }
  if (response.headers.get('x-ratelimit-remaining') === '0') {
    const resetMs = Number(response.headers.get('x-ratelimit-reset')) * 1000;
    return Math.max(resetMs - Date.now(), 0);
  }
  const { message = '' } = await response.clone().json().catch(() => ({}));
  if (response.status === 429 || /rate limit/i.test(message)) {
    return 60_000 * 2 ** attempt;
  }
  // A 403 without rate limit signals is a permission problem: don't retry
  return null;
}

O seu chamador tenta novamente quando a função devolve um número e para após algumas tentativas.

Como testar se a sua aplicação lida com os limites de taxa do GitHub

Raramente atinges o rate limit do GitHub enquanto desenvolves. Envias alguns pedidos, e 5.000 por hora parecem intermináveis. Assim, a forma como testas o controlo da limitação de taxa determina se encontras os bugs antes dos teus utilizadores.

Approach O que encontra Do que sentes falta
Aguarde pelo ambiente de produção Fracassos reais Tudo, até que um utilizador lhe clique
Simula a API nos teus testes, ou deixa o teu agente de programação escrever o mock Se o seu ramo de repetição for executado Os cabeçalhos reais e corpos de erro do GitHub, e a política de retentativas do teu SDK. A tua aplicação também precisa de um switch só de teste para chegar ao mock.
Invoca a API real até que te limite Comportamento real Suporta até 5.000 pedidos, não pode ativar um limite secundário a pedido e arrisca-se a um banimento da sua integração
Intercete o tráfego real da sua aplicação e devolva respostas de limitação de taxa quando solicitado URLs reais, o seu SDK real e política de retentativas, e os próprios cabeçalhos e formato de erro do GitHub Nada na tua aplicação muda, por isso não testa o teu código isoladamente. Guarda os testes unitários para isso.

Experimente na sua app

O Dev Proxy interceta os pedidos da sua aplicação para api.github.com e devolve respostas de limite de taxa ao estilo GitHub, enquanto a sua aplicação continua a chamar os URLs reais. O github-rate-limiting preset contabiliza os teus pedidos no limite de 60 por hora, envia os x-ratelimit-* cabeçalhos e devolve um 429 com API rate limit exceeded quando esgotas o limite. Até lá, os teus pedidos vão para o GitHub e também contam para o teu limite real.

Descarregue a predefinição e inicie o Dev Proxy com ela:

devproxy config get github-rate-limiting
devproxy --config-file "~dataFolder/configs/github-rate-limiting/.devproxy/devproxyrc.json"

Para testar limites secundários, inicie o Dev Proxy com devproxyrc-secondary.json a partir da mesma pasta. Ele devolve aleatoriamente um limite 429 de taxa secundária com um cabeçalho retry-after.

Depois executa a tua aplicação como de costume e vê o que faz. Para instalar Dev Proxy, consulte Configurar Dev Proxy.

Passos seguintes

Ver também