Tip
스로틀링이 처음이신가요? 스로틀링이 무엇인지와 이를 처리하는 방법을 알아봅니다.
한눈에 보기
목표: 앱이 GitHub REST API 속도 제한을 처리하는 방법을 테스트
시간: 15분
Plugins:RateLimitingPlugin, GenericRandomErrorPlugin, RetryAfterPlugin
필수 구성 요소:개발 프록시 설정
앱이 GitHub API를 호출합니다. 사용자 머신에서는 작동하지만, CI 작업이나 대규모 조직, 또는 사용량이 많은 날에는 속도 제한을 초과하게 되어 실패하기 시작합니다. 실제 API에 대해 테스트하려면 요청 한도를 모두 소진한 뒤 최대 1시간 동안 기다렸다가 다시 시도해야 합니다. 개발자 프록시는 선택한 제한 및 기간으로 GitHub 속도 제한을 로컬로 시뮬레이션합니다.
GitHub 반환되는 내용 파악
GitHub REST API에 대해 2가지 종류의 속도 제한이 있습니다.
기본 속도 제한은 시간당 요청 수를 제한합니다. 예를 들어 인증되지 않은 요청의 경우 60개, 개인 액세스 토큰이 있는 요청의 경우 5,000개입니다. 모든 응답에는 현재 위치를 보여 주는 헤더가 포함됩니다.
| Header | Meaning |
|---|---|
x-ratelimit-limit |
시간당 최대 요청 수 |
x-ratelimit-remaining |
현재 창에 남아 있는 요청 수 |
x-ratelimit-reset |
창이 다시 설정되는 시간(UTC epoch 초) |
기본 제한을 초과하면 GitHub 반환 403 되거나 429x-ratelimit-remaining 로 설정됩니다0. 다음 시간 x-ratelimit-reset까지 다시 시도하지 마세요.
보조 속도 제한은 너무 많은 동시 요청 또는 너무 많은 콘텐츠를 너무 빨리 만드는 것과 같은 급증으로부터 GitHub를 보호합니다. 하나를 초과하면 GitHub는 403 또는 429을 보조 속도 제한에 대한 메시지와 함께 반환합니다. 응답에 헤더가 있는 retry-after 경우 몇 초 정도 기다립니다. 그렇지 않으면 1분 이상 기다렸다가 요청이 계속 실패하는 경우 대기 시간을 늘입니다.
GitHub 속도가 제한된 동안 요청을 계속 보내는 통합을 금지할 수 있습니다. 자세한 내용은 GitHub 설명서에서 REST API에 대한 속도 제한을 참조하세요.
기본 요청 제한 시뮬레이션
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
개발자 프록시는 1분마다 처음 5개의 요청을 GitHub로 전달하고 응답에 x-ratelimit-* 헤더를 설정합니다. 6번째 요청부터 Dev Proxy는 창의 끝으로 설정된 0x-ratelimit-reset 속도 제한 응답을 x-ratelimit-remaining 반환합니다. 윈도우가 재설정되기 전에 앱이 API를 다시 호출하면 RetryAfterPlugin 이를 보고하고 요청을 제한합니다.
앱이 다음 사항을 충족하는지 확인하세요:
-
x-ratelimit-remaining에서 읽고0에 도달하기 전에 속도를 늦춥니다. - 속도 제한(rate limit) 응답 후 API 호출을 중지하고
x-ratelimit-reset까지 기다립니다. - 아무 알림 없이 실패하는 대신 "GitHub 속도 제한에 도달하여 14:05에 다시 시도"하는 등 어떤 일이 일어나고 있는지 사용자에게 알립니다.
Note
GitHub 속도 제한을 초과하면 429 반환 403 됩니다. 앱이 statusCode도 처리하는지 테스트하려면 403을 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"
}
}
]
}
]
}
개발자 프록시를 시작하고 앱을 실행합니다. 앱이 API를 다시 호출하기 전에 retry-after 헤더의 초 단위 값만큼 기다리는지 확인합니다. 그렇지 않으면 RetryAfterPlugin가 그것을 보고합니다.
제한 플러그인과 함께 Octokit를 사용하는 경우 onRateLimit 및 onSecondaryRateLimit 핸들러가 실행되고 예상한 결과를 반환하는지 확인합니다.
다음 단계:
RateLimitingPlugin에 대해 자세히 알아보세요.
또한, 다음을 참조하세요.
- Rate-Limit API 응답 시뮬레이션 - API에 대한 속도 제한
- 내 애플리케이션이 제한을 제대로 처리하는지 테스트 - API에서 제한
- RetryAfterPlugin - 재시도 동작 확인
- CI/CD에서 개발 프록시 사용 - 파이프라인에서 복원력 테스트 자동화
Dev Proxy