Test nieuwe pogingen en time-outs in .NET apps die gebruikmaken van Microsoft.Extensions.Http.Resilience

Tip

Nieuw met throttling? Lees meer over throttling en hoe u hiermee omgaat.

In één oogopslag
Doel: Bevestig dat uw .NET HTTP-resilience-handler nieuwe pogingen uitvoert, de wachttijd opvoert en time-outs hanteert zoals verwacht
Tijd: 15 minuten
Plugins:GenericRandomErrorPlugin, RetryAfterPlugin, LatencyPlugin
Vereisten:Dev Proxy instellen, een .NET-app die gebruikmaakt van Microsoft.Extensions.Http.Resilience

U hebt AddStandardResilienceHandler() aan uw HttpClient toegevoegd. Hoe weet je dat het werkt? De API's die u aanroept, mislukken zelden wanneer u dat wilt, en unittests die HttpMessageHandler mocken, slaan de resilience-pijplijn die u wilt testen over.

Dev Proxy bevindt zich tussen uw app en de API. Het retourneert fouten en trage reacties naar uw app, zodat uw app ongewijzigd wordt uitgevoerd en de resilience-handler reageert op echte HTTP-antwoorden. U ziet elke poging in de uitvoer van de Dev Proxy.

Wat de standaard-resilience-handler doet

Voordat u test, weet u wat u kunt verwachten. Met standaardopties: AddStandardResilienceHandler()

Gedrag Default
Nieuwe pogingen ingeschakeld HTTP 500 en hoger, 408, 429, HttpRequestExceptionen TimeoutRejectedException
Aantal herhalingen 3, met exponentiële backoff en jitter, beginnend bij 2 seconden
Retry-After koptekst Gehonoreerd. De handler wacht zo lang als de API vraagt.
Time-out van poging 10 seconden per poging
Totale onderbreking 30 seconden voor het verzoek, inclusief alle herhaalde pogingen

Zie standaardinstellingen voor resilience-handlers voor de volledige lijst met strategieën en hun standaardinstellingen.

Routeer uw app via Dev Proxy

.NET gebruikt de systeemproxy, dus wanneer u Dev Proxy start, worden de aanvragen van uw app onderschept zonder codewijzigingen. Zie Dev Proxy gebruiken met .NET toepassingen voor meer informatie.

Tijdelijke fouten simuleren

Maak een Dev Proxy-configuratie die aanvragen naar uw API laat mislukken met de fouten waarbij de handler het opnieuw probeert. In dit voorbeeld wordt https://api.contoso.comgebruikt. Vervang deze door de URL van de API die door uw app wordt aangeroepen.

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

Voeg de RetryAfterPlugin toe vóór de GenericRandomErrorPlugin in uw configuratiebestand. Als u deze later toevoegt, zorgt GenericRandomErrorPlugin ervoor dat de aanvraag mislukt voordat RetryAfterPlugin deze kan controleren.

Definieer in het foutenbestand een throttlingreactie en twee serverfouten. Met de waarde @dynamic wordt de Retry-After-header ingesteld en krijgt RetryAfterPlugin de instructie te controleren of uw app zo lang wacht voordat deze de API opnieuw aanroept.

Bestand: 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
        }
      ]
    }
  ]
}

Start Dev Proxy en voer uw app uit.

devproxy --config-file devproxyrc.json

Met een foutpercentage van 50% slagen de meeste verzoeken na een of twee nieuwe pogingen. Controleer in de uitvoer van Dev Proxy het volgende:

  • Na een 429-antwoord komt de volgende poging tot dezelfde URL na Retry-After. Dev Proxy gebruikt standaard 5 seconden. Als uw app de API te vroeg aanroept, meldt RetryAfterPlugin dit en wordt de aanvraag beperkt.
  • Uw app verzendt niet meer pogingen dan u hebt geconfigureerd.
  • Aanvragen die u niet opnieuw wilt proberen, zoals een POST die een record maakt, worden slechts één keer verzonden. Als u ze wilt uitsluiten, bel options.Retry.DisableForUnsafeHttpMethods() of options.Retry.DisableFor(...).

Test wat er gebeurt wanneer nieuwe pogingen op zijn

Herhaalde pogingen verbergen korte storingen. U moet ook weten wat uw app doet wanneer de API blijft falen. Start Dev Proxy met een foutpercentage van 100%:

devproxy --config-file devproxyrc.json --failure-rate 100

Dev Proxy toont vier pogingen voor elke aanvraag: de oorspronkelijke aanvraag en 3 nieuwe aanvragen. Na de laatste nieuwe poging gooit de standaardhandler geen uitzondering. Het retourneert de laatste foutrespons aan uw code. Controleer wat uw app ermee doet. Bijvoorbeeld werpt een op en werpt ook een op. Zorg ervoor dat uw app een nuttig bericht weergeeft of terugvalt, in plaats van vast te lopen of een algemene fout weer te geven.

Time-outs

Trage API's activeren een ander pad in de handler. Als u deze wilt testen, gebruikt u de LatencyPlugin om reacties na het verstrijken van de time-out voor pogingen van 10 seconden te vertragen.

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

Start Dev Proxy en voer uw app uit. Elke poging duurt langer dan 10 seconden, dus de time-out voor de poging annuleert deze en de handler probeert opnieuw. Na 30 seconden annuleert de totale time-out het verzoek en krijgt uw code een TimeoutRejectedException. Controleer of uw app deze afvangt en laat de gebruiker zien wat er is gebeurd.

Tip

Als u dezelfde scenario's wilt testen met uw eigen resilience-instellingen, wijzigt u de waarden in uw AddStandardResilienceHandler(options => ...) aanroep en voert u dezelfde Dev Proxy-configuraties opnieuw uit.

Volgende stap

Meer informatie over het simuleren van throttling in elke API.

Zie ook