Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Tip
Впервые сталкиваетесь с ограничением пропускной способности? Узнайте что такое троттлинг и как с ним работать.
На первый взгляд
Цель: Проверка того, как приложение обрабатывает ограничения частоты запросов REST API GitHub
Время: 15 минут
Подключаемые модули:RateLimitingPlugin, GenericRandomErrorPlugin, RetryAfterPlugin
Предварительные требования:настройка прокси-сервера разработки
Приложение вызывает API GitHub. На вашей машине это работает, но затем задание CI, большая организация или напряжённый день превышают лимит запросов, и всё начинает давать сбои. Чтобы протестировать его с реальным API, вам потребуется исчерпать свой лимит запросов, а затем подождать до часа, прежде чем вы сможете повторить попытку. Dev Proxy имитирует ограничения частоты запросов GitHub локально, с ограничением и временным интервалом, которые вы выбираете.
Узнайте, что возвращает GitHub
GitHub имеет 2 типа лимитов запросов для REST API.
Основные лимиты частоты запросов ограничивают количество запросов, которые вы делаете в час. Например, 60 для неаутентифицированных запросов и 5000 для запросов с персональным токеном доступа. Каждый ответ содержит заголовки, которые показывают, где вы находитесь:
| Header | Meaning |
|---|---|
x-ratelimit-limit |
Максимальное количество запросов в час |
x-ratelimit-remaining |
Количество запросов, оставшихся в текущем окне |
x-ratelimit-reset |
Время, когда окно сбрасывается, в секундах эпохи UTC |
При превышении основного ограничения GitHub возвращает 403 или 429 с x-ratelimit-remaining, заданным значением 0. Не повторяйте попытку до времени, указанного в x-ratelimit-reset.
Вторичные ограничения скорости защищают GitHub от всплесков, таких как слишком много одновременных запросов или создание слишком большого количества содержимого слишком быстро. Когда вы превышаете один из лимитов, GitHub возвращает 429 или 403 с сообщением о дополнительном ограничении скорости. Если ответ имеет заголовок retry-after, подождите столько секунд. В противном случае подождите по крайней мере минуту и увеличьте время ожидания, если запрос завершается сбоем.
GitHub может запретить интеграции, которые продолжают отправлять запросы, пока для них действует ограничение частоты запросов. Дополнительные сведения см. в разделе "Ограничения скорости" для REST API в документации по GitHub.
Имитация основного лимита запросов
Используйте RateLimitingPlugin для подсчета запросов и возврата заголовков лимита запросов GitHub. Чтобы протестировать, не ожидая часа, используйте небольшое ограничение и короткое окно.
Файл: 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
Добавьте RetryAfterPlugin перед RateLimitingPlugin в вашем файле конфигурации. Если вы добавите его после, RateLimitingPlugin обрабатывает запрос, прежде чем RetryAfterPlugin сможет его проверить.
В файле настраиваемого ответа определите ответ, который GitHub возвращает при превышении основного лимита частоты запросов.
Файл: 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"
}
}
Запустите Dev Proxy и запустите приложение.
devproxy --config-file devproxyrc.json
Прокси-сервер разработки пересылает первые 5 запросов в каждую минуту в GitHub и устанавливает заголовки x-ratelimit-* в ответах. Начиная с 6-го запроса Dev Proxy возвращает ответ об ограничении скорости с x-ratelimit-remaining, заданным значением 0, и x-ratelimit-reset, установленным на конец окна. Если приложение снова вызывает API до сброса окна, RetryAfterPlugin сообщает об этом и регулирует запрос.
Убедитесь, что ваше приложение:
- Считывает
x-ratelimit-remainingи замедляется до достижения0. - Останавливает вызов API после ответа о превышении лимита запросов и ожидает до
x-ratelimit-reset. - Сообщает пользователю о том, что происходит, например: «достигнут лимит запросов GitHub, повторная попытка в 14:05», вместо того чтобы молча завершаться с ошибкой.
Note
GitHub возвращает значение 403 или 429 при превышении лимита запросов. Чтобы проверить, что приложение также обрабатывает 403, измените statusCode на 403.
RetryAfterPlugin отслеживает только ответы 429, поэтому он не сообщает о ранних повторных попытках после 403.
Tip
Dev Proxy перенаправляет запросы в GitHub до достижения имитированного ограничения. Эти запросы также засчитываются в ваш фактический лимит запросов GitHub.
Имитация вторичных ограничений скорости запросов
Ограничения вторичной частоты запросов возникают всплесками и включают retry-after заголовок. Используйте GenericRandomErrorPlugin, чтобы вернуть их случайным образом.
Файл: 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
}
}
Файл: 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"
}
}
]
}
]
}
Запустите Dev Proxy и запустите приложение. Убедитесь, что приложение ждёт указанное в заголовке retry-after количество секунд, прежде чем снова обратиться к API. Если это не так, RetryAfterPlugin сообщает об этом.
Если вы используете Octokit с подключаемым модулем регулирования, убедитесь, что ваши обработчики onRateLimit и onSecondaryRateLimit выполняются и возвращают ожидаемый результат.
Следующий шаг
Узнать больше о RateLimitingPlugin.
См. также
- Сымитировать ответы API Rate-Limit — лимиты запросов для любого API
- Проверка того, что мое приложение корректно обрабатывает троттлинг — троттлинг в любом API
- RetryAfterPlugin — проверка поведения повторных попыток
- Использование прокси-сервера разработки в CI/CD — автоматизация тестирования устойчивости в конвейере