Testování, jak vaše aplikace zpracovává limity rychlosti rozhraní API GitHub

Tip

Neznáte ještě omezování rychlosti? Zjistěte, co je throttling a jak ho řešit.

Na první pohled
Cíl: Otestujte, jak aplikace zpracovává limity rychlosti rozhraní REST API GitHub
Čas: 15 minut
Moduly plug-in:RateLimitingPlugin, GenericRandomErrorPlugin, RetryAfterPlugin
Požadavky:Nastavení dev proxy serveru

Aplikace volá rozhraní API GitHub. Funguje na vašem počítači, pak ho úloha CI, velká organizace nebo během vytíženého dne přetlačí přes limit požadavků a začne selhávat. Pokud ho chcete otestovat na skutečném rozhraní API, musíte vyčerpat svůj limit požadavků a pak počkat až hodinu, než to budete moct zkusit znovu. Dev Proxy simuluje GitHub omezení rychlosti místně s nastaveným limitem a časovým oknem, které zvolíte.

Zjistit, co GitHub vrací

GitHub má 2 druhy omezení rychlosti pro rozhraní REST API.

Primární míra omezuje počet požadavků, které za hodinu provedete. Například 60 pro neověřené požadavky a 5 000 pro požadavky s osobním přístupovým tokenem. Každá odpověď obsahuje hlavičky, které ukazují, kde jste:

Header Meaning
x-ratelimit-limit Maximální počet požadavků za hodinu
x-ratelimit-remaining Počet požadavků, které zůstaly v aktuálním okně
x-ratelimit-reset Čas resetování okna v sekundách epochy UTC

Když překročíte primární limit, GitHub vrátí 403 nebo 429 s hodnotou x-ratelimit-remaining nastavenou na 0. Nezkoušejte to znovu, dokud nenastane čas uvedený v x-ratelimit-reset.

Sekundární limity frekvence požadavků chrání GitHub před nárazovým zatížením, jako je příliš mnoho souběžných požadavků nebo vytváření příliš velkého množství obsahu příliš rychle. Když překročíte jednu, GitHub vrátí 403 nebo 429 se zprávou o limitu sekundární rychlosti. Pokud má odpověď hlavičku retry-after , počkejte tolik sekund. Jinak počkejte aspoň minutu a v případě selhání požadavku zvyšte dobu čekání.

GitHub můžou zakázat integrace, které dál odesílají požadavky, i když jsou omezené rychlostí. Další informace najdete v tématu Omezení rychlosti pro rozhraní REST API v dokumentaci k GitHub.

Simulace limitu primární rychlosti

Pomocí rateLimitingPlugin můžete spočítat požadavky a vracet hlavičky limitu rychlosti GitHub. Pokud chcete testovat, aniž byste museli čekat hodinu, použijte malý limit a krátké okno.

Soubor: 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

Přidejte RetryAfterPlugin před RateLimitingPlugin ve vašem konfiguračním souboru. Pokud ho přidáte potom, RateLimitingPlugin zpracuje požadavek, než ho RetryAfterPlugin bude moct zkontrolovat.

V souboru vlastní odpovědi definujte odpověď, která GitHub vrátí, když překročíte limit primární rychlosti.

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

Spusťte Dev Proxy a spusťte aplikaci.

devproxy --config-file devproxyrc.json

Dev Proxy předává prvních 5 požadavků v každé minutě, aby GitHub a nastavil x-ratelimit-* hlavičky odpovědí. Z 6. požadavku na službu Dev Proxy vrátí odpověď limitu rychlosti s x-ratelimit-remaining nastavenou 0 na a x-ratelimit-reset nastavenou na konec okna. Pokud vaše aplikace znovu volá rozhraní API před resetováním okna, RetryAfterPlugin to zaznamená a omezí požadavek.

Zkontrolujte, že vaše aplikace:

  • x-ratelimit-remaining Čte a zpomaluje, než dosáhne 0.
  • Zastaví volání rozhraní API po odpovědi o překročení limitu požadavků a počká na x-ratelimit-reset.
  • Informuje uživatele o tom, co se děje, například „bylo dosaženo limitu požadavků GitHubu, opakování v 14:05“, místo aby aplikace tiše selhala.

Note

GitHub vrátí buď 403, nebo 429, když překročíte limit požadavků. Pokud chcete otestovat, že aplikace také zpracovává 403 , změňte statusCode na 403. RetryAfterPlugin sleduje pouze odpovědi 429, takže nehlásí časné opakované pokusy po 403.

Tip

Dev Proxy předává požadavky na GitHub až do dosažení simulovaného limitu. Tyto požadavky se započítávají i do skutečného limitu počtu požadavků GitHubu.

Simulovat sekundární omezení četnosti požadavků

Sekundární limity počtu požadavků nastávají ve vlnách a obsahují hlavičku retry-after. Použijte GenericRandomErrorPlugin k jejich náhodnému vrácení.

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

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

Spusťte Dev Proxy a spusťte aplikaci. Zkontrolujte, jestli vaše aplikace čeká po dobu počtu sekund uvedeného v hlavičce retry-after, než znovu zavolá rozhraní API. Pokud ne, RetryAfterPlugin to nahlásí.

Pokud používáte Octokit s modulem plug-in omezování, zkontrolujte, jestli se handlery onRateLimit a onSecondaryRateLimit spustí a že vrátí očekávaný výsledek.

Další krok

Další informace o nástroji RateLimitingPlugin.

Viz také