Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ha egy API túl lassú, a .NET-alkalmazás 2 kivételből 1-et kap, attól függően, hogy melyik időtúllépés aktiválódott.
HttpClient.Timeout kivált egy TaskCanceledException. A standard rugalmassági kezelő Microsoft.Extensions.Http.Resilience dob a Pollyból TimeoutRejectedException. Különböző helyekről származnak, különböző alapértelmezett értékekkel rendelkeznek, és külön catch blokkokra van szükségük.
Melyik időtúllépés aktiválódott
| Időkorlát | Alapértelmezett | Amit a kódod kap | A hely, ahol beállítja |
|---|---|---|---|
HttpClient.Timeout |
100 másodperc |
TaskCanceledException, amelyben a(z) TimeoutException a(z) InnerException szerepét tölti be (.NET 5 és újabb) |
HttpClient.Timeout |
| A standard kezelő kísérletének időtúllépése | Kísérletenként 10 másodperc | Először semmi: a kezelőprogram újra megpróbálja a kísérletet | AddStandardResilienceHandler(options => ...) |
| Standard kezelőprogram teljes időtúllépése | 30 másodperc, az újrapróbálkozásokat is beleértve | Polly.Timeout.TimeoutRejectedException |
AddStandardResilienceHandler(options => ...) |
HttpClient.Timeout
HttpClient.Timeout minden olyan kérésre vonatkozik, amelyet a HttpClient példány küld. Ha egy kéréshez eltérő időtúllépést szeretne használni, adjon át egy CancellationToken-t egy saját időtúllépéssel rendelkező CancellationTokenSource-ből. A kettő közül a rövidebb érvényes. A kikapcsoláshoz állítsa a(z) Timeout.InfiniteTimeSpan elemet erre:
Az .NET 5-ös és újabb verzióiban az időtúllépés egy TimeoutException belső kivétellel rendelkező TaskCanceledException kivételt dob. A .NET Core korábbi verzióiban a belső kivétel nem létezik. A .NET-keretrendszerben ehelyett HttpRequestException kap. További információ: HttpClient.Timeout és HTTP-kérések végrehajtása a HttpClient osztállyal.
A TaskCanceledException azt is jelenti, hogy valaki visszavonta a kérelmet, például egy felhasználó, aki bezárta az oldalt. Ha meg szeretné különböztetni az időtúllépést a megszakítástól, ellenőrizze a ex.InnerException is TimeoutException elemet, vagy ellenőrizze, hogy a saját tokenje meg van-e szakítva.
A standard rezilienciakezelő
AddStandardResilienceHandler() egy sebességkorlátozót, egy teljes időtúllépést, egy újrapróbálkozást, egy áramkör-megszakítót és egy kísérletenkénti időtúllépést fűz össze. Ha egy kísérlet több mint 10 másodpercet vesz igénybe, a kísérlet időtúllépése megszakítja azt, és az újrapróbálkozási stratégia újra próbálkozik: legfeljebb 3 újrapróbálkozás, exponenciális visszalépéssel és jitterrel, 2 másodperces kezdő értékkel. Ha a teljes kérelem, beleértve az újrapróbálkozásokat is, több mint 30 másodpercet vesz igénybe, a teljes időtúllépés megszakítja azt, és a kódod egy TimeoutRejectedException kap.
TimeoutRejectedException
Exception-ből származik. Ez sem egy TimeoutException, sem egy HttpRequestException, így egy catch (HttpRequestException) blokk nem fogja meg. Az alapértelmezett értékek teljes listáját a Standard reziliencia-kezelő alapértelmezései című témakörben találja.
Ha például egy .NET 10-es alkalmazás, amely a standard kezelő alapértelmezett beállítását használja, olyan API-t hív meg, amelynél egy-egy válasz 11–15 másodpercet vesz igénybe, az alkalmazás 30 másodpercet követően kap egy TimeoutRejectedException, és a catch (HttpRequestException) blokk nem fut.
HttpClient-időtúllépések kezelése
- Kezelje mindkét kivételt ott, ahol meghívja az API-t. Ha a standard kezelőt használja, kapja el a
TimeoutRejectedException. ElkapTaskCanceledExceptiona következőhöz:HttpClient.Timeout. - Különböztesse meg az időtúllépést a lemondástól. Csak akkor kezelje időtúllépésként
TaskCanceledException, ha a belső kivétele egyTimeoutException. Amikor a hívó megszakította, állítsa le csendben. - Az API-nak megfelelő időtúllépések kiválasztása. Ha az API gyakran 10 másodpercnél tovább tart, módosítsa a kísérlethez és a teljes időtúllépéshez tartozó időkorlátokat a következőben:
AddStandardResilienceHandler(options => ...) - Ne próbálja újra sem a
POST-t, sem aPATCH-t, hacsak az API nem teszi biztonságossá. A standard kezelő alapértelmezés szerint minden metódust újrapróbál, beleértve a(z)POSTmetódust is. A(z)DELETEmeghívásával kizárhatja a(z)POST,PUT,PATCH,options.Retry.DisableForUnsafeHttpMethods()ésPUTelemeket, vagy a(z)DELETEhasználatával továbbra is újrapróbálhatja az idempotensCONNECTésoptions.Retry.DisableFor(HttpMethod.Post, HttpMethod.Patch)elemeket. - Mondja el a felhasználónak, mi történt. Az általános hiba helyett jelenítse meg ezt: „a szolgáltatás lassú, próbálkozzon újra”.
using Polly.Timeout;
public async Task<string?> GetForecastAsync(HttpClient client, CancellationToken cancellationToken)
{
try
{
return await client.GetStringAsync("https://api.contoso.com/forecast", cancellationToken);
}
catch (TimeoutRejectedException)
{
// Standard resilience handler: total timeout expired after all retries
return null;
}
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
// HttpClient.Timeout expired
return null;
}
catch (HttpRequestException)
{
// Network error, or an error status code after all retries
return null;
}
}
Annak tesztelése, hogy az alkalmazás kezeli-e az időtúllépéseket
Fejlesztés közben ritkán lát időtúllépést, így a catch blokkok ritkán futnak. Az, ahogyan tesztelsz, határozza meg, hogy a felhasználóid előtt találod-e meg a hibákat.
| Approach | Mit talál? | Amit elmulaszt |
|---|---|---|
| Várjon az élesítésig | Valós idejű időkorlátok | Minden addig, amíg egy felhasználó rá nem kattint |
| Mockolja az API-t a tesztekben, vagy hagyja, hogy a kódoló asszisztens megírja a mockot | Fut-e a catch blokk, ha a mock a megfelelő kivételt dobja |
A valódi HttpClient beállítás, a reziliencia-kezelő újrapróbálkozásai és a kivétel, amelyet ténylegesen dob. Az alkalmazásnak egy csak tesztelési kapcsolóra is szüksége van a mock eléréséhez. |
| Hívja meg a valódi API-t, és remélje, hogy lassú | Valós viselkedés | Az API-t nem lehet szándékosan lassúvá tenni |
| Fogd el az alkalmazás valós forgalmát, és késleltesd a válaszokat | Az Ön valódi HttpClient, rezilienciakezelője és kivételei |
Az alkalmazásban semmi sem változik, így nem teszteli a kódot elkülönítve. Arra valók az egységtesztek. |
Próbálja ki a saját alkalmazásában
A Dev Proxy elfogja az alkalmazás api-nak küldött kéréseit, és késlelteti a válaszokat a LatencyPlugin használatával. .NET a rendszerproxyt használja, így nem kell módosítania a kódot. Ez a példa minden választ 11–15 másodperccel késleltet, ami hosszabb, mint a standard kezelő 10 másodperces próbálkozási időkorlátja. Cserélje le a(z) https://api.contoso.com elemet az alkalmazás által hívott API URL-címére.
Fájl: 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
}
}
Indítsa el a Dev Proxyt a(z) devproxy --config-file devproxyrc.json paranccsal, majd futtassa az alkalmazását. Minden kísérlet túllépi az időkorlátot, a kezelőprogram újrapróbálkozik, és 30 másodperc múlva a kód kap egy TimeoutRejectedException. Ehelyett állítsa a(z) minMs értékét a konfigurált időtúllépésnél magasabbra a(z) HttpClient.Timeout teszteléséhez. A beállítás részleteiért lásd: Dev Proxy használata .NET alkalmazásokkal. A Dev Proxy telepítéséhez lásd: Dev Proxy beállítása.