Tip
스로틀링이 처음이신가요? 스로틀링이 무엇인지와 이를 처리하는 방법을 알아봅니다.
한눈에 보기
목표: .NET HTTP 복원력 처리기가 예상대로 재시도하고, 백오프하며, 시간 초과되는지 확인
시간: 15분
Plugins:GenericRandomErrorPlugin, RetryAfterPlugin, LatencyPlugin
필수 조건:Dev Proxy를 설정합니다, Microsoft.Extensions.Http.Resilience를 사용하는 .NET 앱
HttpClient에 AddStandardResilienceHandler()을 추가했습니다. 작동한다는 것을 어떻게 알 수 있나요? 호출하는 API는 원할 때 거의 실패하지 않으며, HttpMessageHandler를 모의하는 단위 테스트는 테스트하려는 복원력 파이프라인을 건너뜁니다.
개발자 프록시는 앱과 API 사이에 있습니다. 앱에 오류 및 느린 응답을 반환하므로 앱이 변경되지 않고 실행되고 복원력 처리기가 실제 HTTP 응답에 반응합니다. Dev Proxy 출력에서 모든 시도를 볼 수 있습니다.
표준 복원력 처리기가 수행하는 작업
테스트하기 전에 예상되는 내용을 알아 두세요. 기본 옵션 사용 시 AddStandardResilienceHandler():
| Behavior | Default |
|---|---|
| 다시 시도 | HTTP 500 이상, 408, 429, HttpRequestException 및 TimeoutRejectedException |
| 재시도 횟수 | 3, 지수 백오프 및 지터, 2초에서 시작 |
Retry-After 헤더 |
영광입니다. 처리기는 API가 요청한 시간만큼 기다립니다. |
| 시도 시간 제한 | 시도당 10초 |
| 총 타임아웃 | 모든 재시도를 포함한 요청 시간 30초 |
전략 및 해당 기본값의 전체 목록은 표준 복원력 핸들러 기본값을 참조하세요.
Dev Proxy를 통해 앱 라우팅
.NET 시스템 프록시를 사용하므로 개발자 프록시를 시작하면 코드 변경 없이 앱의 요청을 가로채게 됩니다. 자세한 내용은 .NET 애플리케이션에서 개발 프록시 사용을 참조하세요.
일시적 오류 시뮬레이션
API 요청을 처리기가 재시도하는 오류로 실패시키는 Dev Proxy 구성을 만듭니다. 이 예제에서는 https://api.contoso.com를 사용합니다. 이를 앱이 호출하는 API의 URL로 바꾸세요.
파일: 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": "transientErrors"
}
],
"urlsToWatch": [
"https://api.contoso.com/*"
],
"transientErrors": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.schema.json",
"errorsFile": "transient-errors.json",
"rate": 50
}
}
Caution
구성 파일에 RetryAfterPlugin 앞에 GenericRandomErrorPlugin을 추가합니다. 나중에 추가하면 GenericRandomErrorPlugin가 확인하기 전에 RetryAfterPlugin가 요청을 실패시킵니다.
오류 파일에서 스로틀링 응답과 두 개의 서버 오류를 정의합니다.
@dynamic 값은 Retry-After 헤더를 설정하고 앱이 API를 다시 호출하기 전에 그 시간만큼 기다리는지 RetryAfterPlugin에서 확인하도록 지시합니다.
파일: transient-errors.json
{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
"errors": [
{
"request": {
"url": "https://api.contoso.com/*"
},
"responses": [
{
"statusCode": 429,
"headers": [
{
"name": "Retry-After",
"value": "@dynamic"
}
]
},
{
"statusCode": 500
},
{
"statusCode": 503
}
]
}
]
}
Dev Proxy를 시작하고 앱을 실행합니다.
devproxy --config-file devproxyrc.json
실패율이 50%일 때 대부분의 요청은 한두 번의 재시도 후 복구됩니다. 개발 프록시 출력에서 다음을 확인하세요:
- 429 응답 후 동일한 URL에 대한 다음 시도는
Retry-After시간 후에 다시 시도합니다. Dev Proxy는 기본적으로 5초를 사용합니다. 앱이 API를 너무 일찍 호출하는 경우RetryAfterPlugin에서 이를 보고하고 요청을 제한합니다. - 사용자의 앱은 사용자가 구성한 것보다 더 많은 시도를 보내지 않습니다.
- 레코드를 생성하는
POST와 같은, 다시 시도하지 않으려는 요청은 한 번만 전송됩니다. 제외하려면options.Retry.DisableFor(...)또는options.Retry.DisableForUnsafeHttpMethods()을 호출하세요.
재시도 횟수가 모두 소진되면 어떻게 되는지 테스트
재시도는 일시적인 실패를 숨깁니다. 또한 API가 계속 실패할 때 앱이 수행하는 작업을 알아야 합니다. 100% 실패율로 Dev Proxy 시작:
devproxy --config-file devproxyrc.json --failure-rate 100
개발자 프록시는 각 요청에 대해 4번의 시도(원래 요청 및 3번의 재시도)를 표시합니다. 마지막 재시도 후에는 표준 처리기가 예외를 발생시키지 않습니다. 코드에 마지막 오류 응답을 반환합니다. 앱이 그것으로 무엇을 하는지 확인합니다. 예를 들어 EnsureSuccessStatusCode()는 HttpRequestException 예외를 발생시키고, GetStringAsync()도 예외를 발생시킵니다. 앱에서 일반적인 오류를 표시하거나 충돌하는 대신 유용한 메시지를 표시하거나 폴백해야 합니다.
테스트 시간 제한
느린 API는 처리기에서 다른 경로를 트리거합니다. 테스트하려면 LatencyPlugin을 사용하여 10초 시도 시간 제한을 초과하도록 응답을 지연하세요.
파일: devproxyrc.json
{
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
"plugins": [
{
"name": "LatencyPlugin",
"enabled": true,
"pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
"configSection": "slowApi"
}
],
"urlsToWatch": [
"https://api.contoso.com/*"
],
"slowApi": {
"$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/latencyplugin.schema.json",
"minMs": 11000,
"maxMs": 15000
}
}
Dev Proxy를 시작하고 앱을 실행합니다. 각 시도에는 10초보다 오래 걸리므로 시도 시간 제한이 이를 취소하고 처리기가 다시 시도합니다. 30초 후에 총 시간 제한은 요청을 취소하고 코드가 TimeoutRejectedException를 받습니다. 앱이 이를 catch하고 사용자에게 어떤 일이 일어났는지 알려 주는지 확인합니다.
Tip
고유한 복원력 설정으로 동일한 시나리오를 테스트하려면 AddStandardResilienceHandler(options => ...) 호출의 값을 변경하고 동일한 개발자 프록시 구성을 다시 실행합니다.
다음 단계:
모든 API에서 스로틀링을 시뮬레이션하는 방법에 대해 자세히 알아봅니다.
또한, 다음을 참조하세요.
- .NET 애플리케이션에서 개발 프록시 사용 - .NET 설정
- GenericRandomErrorPlugin - 전체 참조
- RetryAfterPlugin - 재시도 동작 확인
- LatencyPlugin - 느린 응답 시뮬레이트
- 변경 요청 실패율 - 요청이 실패하는 빈도 조정
- CI/CD에서 개발 프록시 사용 - 파이프라인에서 복원력 테스트 자동화
Dev Proxy