Testa hur din app hanterar GitHub API-hastighetsgränser

Tip

Nybörjare på strypning? Lär dig vad strypning innebär och hur du hanterar det.

Överblick
Mål: Testa hur din app hanterar GitHub REST API-hastighetsbegränsningar
Tid: 15 minuter
Pluginer:RateLimitingPlugin, GenericRandomErrorPlugin, RetryAfterPlugin
Krav:Konfigurera Dev Proxy

Din app anropar GitHub API. Det fungerar på din datorn, sedan gör ett CI-jobb, en stor organisation eller en upptagen dag att det överskrider gränsen för antalet förfrågningar och det börjar fallera. Om du vill testa det mot det verkliga API:et måste du använda upp anropsgränsen och sedan vänta upp till en timme innan du kan försöka igen. Dev Proxy simulerar GitHubs gränser för begärandefrekvens lokalt, med en gräns och ett tidsfönster som du väljer.

Ta reda på vad GitHub returnerar

GitHub har två typer av begränsningar för begärandefrekvens för REST-API:et.

Primära frekvensgränser begränsar hur många begäranden du gör per timme. Till exempel 60 för oautentiserade begäranden och 5 000 för begäranden med en personlig åtkomsttoken. Varje svar innehåller rubriker som visar var du befinner dig:

Header Meaning
x-ratelimit-limit Maximalt antal begäranden per timme
x-ratelimit-remaining Antalet begäranden som finns kvar i det aktuella fönstret
x-ratelimit-reset Tiden då fönstret återställs i UTC-epoksekunder

När du överskrider den primära gränsen returnerar GitHub 403 eller 429 med x-ratelimit-remaining satt till 0. Försök inte igen förrän tiden som anges i x-ratelimit-reset har passerat.

Sekundära frekvensbegränsningar skyddar GitHub från plötsliga toppar, till exempel för många samtidiga begäranden eller att för mycket innehåll skapas för snabbt. När du överskrider en sådan gräns returnerar GitHub 403 eller 429 med ett meddelande om en sekundär hastighetsgräns. Om svaret har en retry-after rubrik väntar du så många sekunder. Annars, vänta åtminstone en minut och öka väntetiden om begäran fortfarande misslyckas.

GitHub kan blockera integrationer som fortsätter att skicka förfrågningar när de har nått gränsen för antal förfrågningar. Mer information finns i Hastighetsbegränsningar för REST-API:et i dokumentationen om GitHub.

Simulera den primära begränsningen för begärandefrekvens

Använd RateLimitingPlugin för att räkna begäranden och returnera GitHubs rate limit-headers. Om du vill testa utan att vänta en timme använder du en liten gräns och ett kort fönster.

Fil: 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"
  }
}

Försiktighet

Lägg till RetryAfterPlugin före RateLimitingPlugin i din konfigurationsfil. Om du lägger till den efter, hanterar RateLimitingPlugin begäran innan RetryAfterPlugin kan kontrollera den.

I den anpassade svarsfilen definierar du det svar som GitHub returnerar när du överskrider den primära gränsen för begärandefrekvens.

Fil: 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"
  }
}

Starta Dev Proxy och kör din app.

devproxy --config-file devproxyrc.json

Dev Proxy vidarebefordrar de första 5 begärandena varje minut till GitHub och anger headerna x-ratelimit-* i svaren. Från och med den 6:e begäran returnerar Dev Proxy svar för hastighetsbegränsning med x-ratelimit-remaining inställt på 0 och x-ratelimit-reset inställt på slutet av tidsfönstret. Om din app anropar API:et igen innan fönstret återställs rapporterar RetryAfterPlugin det och begränsar begäran.

Kontrollera att din app:

  • Avläser x-ratelimit-remaining och saktar ner innan den når 0.
  • Slutar anropa API:et efter ett svar om hastighetsbegränsning och väntar tills x-ratelimit-reset.
  • Meddelar användaren vad som händer, till exempel "GitHubs gräns för antal anrop har nåtts, försöker igen kl. 14:05", i stället för att misslyckas utan att säga till.

Note

GitHub returnerar antingen 403 eller 429 när du överskrider gränsen för antalet begäranden. Om du vill testa att din app också hanterar 403 ändrar du statusCode till 403. RetryAfterPlugin spårar bara 429-svar, så den rapporterar inte tidiga återförsök efter en 403.

Tip

Dev Proxy vidarebefordrar begäranden till GitHub tills den simulerade gränsen har nåtts. Dessa begäranden räknas även mot din verkliga GitHub-gräns för begäranden.

Simulera sekundära frekvensbegränsningar

Sekundära frekvensbegränsningar kommer i korta toppar och innehåller en retry-after header. Använd GenericRandomErrorPlugin för att returnera dem slumpmässigt.

Fil: 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
  }
}

Fil: 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"
          }
        }
      ]
    }
  ]
}

Starta Dev Proxy och kör din app. Kontrollera att appen väntar det antal sekunder som anges i rubriken retry-after innan den anropar API:et igen. Om den inte gör det, rapporterar RetryAfterPlugin det.

Om du använder Octokit med throttling-pluginet kontrollerar du att dina onRateLimit- och onSecondaryRateLimit-hanterare körs och att de returnerar det resultat du förväntar dig.

Nästa steg

Läs mer om RateLimitingPlugin.

Se även