C# Academy · leksjon

Grunnleggende robusthet: retry og backoff

Implementer enkle retries med eksponentiell backoff og jitter, skill mellom midlertidige og fatale feil, begrens forsinkelsene, og stopp ved kansellering.

Leksjon 3 av 38 trinn

Grunnleggende robusthet: retry og backoff er en gratis leksjon i C# Academy på CoddyKit. Dette er leksjon 3 av 3. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i C# Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i C# Academy inneholder totalt 3 leksjoner.

Hvorfor nye forsøk og backoff

Mål: Gjør kall motstandsdyktige.

  • Prøv på nytt ved forbigående feil
  • Bruk eksponentiell backoff og jitter
  • Angi et maksimalt antall forsøk og en maksimal forsinkelse
  • Stopp ved fatale feil eller kansellering

Klassifiser feil

Forbigående: tidsavbrudd, 429/5xx og midlertidige nettverksforstyrrelser.

Fatale: ugyldig forespørsel, manglende autorisasjon og valideringsfeil – ikke prøv på nytt.

Regel: Prøv bare på nytt når det kan lykkes senere.

Hjelper for backoff

En liten hjelpefunksjon øker forsinkelsen for hvert forsøk og legger til litt jitter. Begrens også den maksimale forsinkelsen.

using System;
using System.Threading;
using System.Threading.Tasks;

public static class Backoff
{
  // Compute delay = min(base * 2^attempt, cap) + jitter
  public static int ComputeDelayMs(int attempt, int baseMs, int capMs, int jitterMs, Random rng)
  {
    long exp = (long)baseMs << attempt; // base * 2^attempt
    if (exp > capMs) exp = capMs;
    int jitter = rng.Next(0, jitterMs + 1); // [0..jitterMs]
    return (int)exp + jitter;
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Random rng = new Random(123);
    for (int i = 0; i < 5; i++)
    {
      int d = Backoff.ComputeDelayMs(i, 100, 2000, 50, rng);
      Console.WriteLine("Attempt " + i + " -> " + d + " ms");
    }
  }
}

Wrapper for nye forsøk

Pakk inn kallet: Prøv bare på nytt ved forbigående unntak, og stopp ved andre unntak. Hvert nytt forsøk venter lenger og bruker jitter.

using System;
using System.Threading;
using System.Threading.Tasks;

public class Program
{
  static readonly Random Rng = new Random();

  // Simulate an operation that sometimes fails transiently.
  static async Task<string> FlakyAsync()
  {
    await Task.Delay(60);
    // 50% chance of transient failure
    if (DateTime.UtcNow.Ticks % 2 == 0) throw new TimeoutException("Transient");
    return "OK";
  }

  static async Task<T> RetryAsync<T>(Func<Task<T>> action, int maxAttempts)
  {
    int baseMs = 100, capMs = 2000, jitterMs = 50;
    for (int attempt = 0; attempt < maxAttempts; attempt++)
    {
      try
      {
        return await action();
      }
      catch (TimeoutException)
      {
        if (attempt == maxAttempts - 1) throw; // out of retries
        int delay = Backoff.ComputeDelayMs(attempt, baseMs, capMs, jitterMs, Rng);
        await Task.Delay(delay);
      }
      catch (Exception)
      {
        // Non-transient (unknown) -> do not retry
        throw;
      }
    }
    throw new InvalidOperationException("Unreachable");
  }

  public static void Main(string[] args)
  {
    try
    {
      string s = RetryAsync(FlakyAsync, 5).GetAwaiter().GetResult();
      Console.WriteLine("Result: " + s);
    }
    catch (Exception ex)
    {
      Console.WriteLine("Failed: " + ex.GetType().Name);
    }
  }
}

Budsjetterte nye forsøk

Legg til et globalt budsjett via kansellering: send token til både operasjonen og backoff-forsinkelsene.

using System;
using System.Threading;
using System.Threading.Tasks;

public static class RetryUtil
{
  static readonly Random Rng = new Random();

  public static async Task<T> RetryAsync<T>(Func<CancellationToken, Task<T>> action, int maxAttempts, CancellationToken ct)
  {
    int baseMs = 100, capMs = 1500, jitterMs = 50;
    for (int attempt = 0; attempt < maxAttempts; attempt++)
    {
      ct.ThrowIfCancellationRequested();
      try
      {
        return await action(ct);
      }
      catch (TimeoutException)
      {
        if (attempt == maxAttempts - 1) throw;
        int delay = Backoff.ComputeDelayMs(attempt, baseMs, capMs, jitterMs, Rng);
        await Task.Delay(delay, ct); // pass token so we can abort waiting
      }
    }
    throw new InvalidOperationException("Unreachable");
  }
}

public class Program
{
  static async Task<string> SometimesSlowAsync(CancellationToken ct)
  {
    await Task.Delay(200, ct);
    if (DateTime.UtcNow.Millisecond % 3 != 0) throw new TimeoutException("Transient");
    return "OK";
  }

  public static void Main(string[] args)
  {
    var cts = new CancellationTokenSource();
    cts.CancelAfter(800); // overall budget

    try
    {
      string s = RetryUtil.RetryAsync(SometimesSlowAsync, 5, cts.Token).GetAwaiter().GetResult();
      Console.WriteLine("Done: " + s);
    }
    catch (OperationCanceledException) { Console.WriteLine("Canceled"); }
    catch (Exception ex) { Console.WriteLine("Failed: " + ex.Message); }
  }
}

Retningslinjer

Tips:

  • Prøv bare på nytt ved idempotente kall.
  • Bruk maksgrenser for antall forsøk og forsinkelse.
  • Legg til litt jitter for å unngå samtidige belastningstopper.
  • Logg den endelige feilen med årsak og antall forsøk.

Definisjon av backoff

Hurtigsjekk: Hva beskriver best eksponentiell backoff med jitter?

Oppsummering

Oppsummering: Prøv bare på nytt ved forbigående feil, øk forsinkelsene eksponentielt med en maksgrense, legg til jitter, og stopp ved kansellering eller fatale feil.

Gratis å komme i gang

Lær deg C# med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
93
Leksjoner
346

Ofte stilte spørsmål

Er leksjonen «Grunnleggende robusthet: retry og backoff» gratis?

Ja – hele teksten i «Grunnleggende robusthet: retry og backoff» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av C# Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i C# Academy inneholder totalt 3 leksjoner.

Hva lærer jeg i «Grunnleggende robusthet: retry og backoff»?

Implementer enkle retries med eksponentiell backoff og jitter, skill mellom midlertidige og fatale feil, begrens forsinkelsene, og stopp ved kansellering. Du øver på C# Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med C# Academy?

Ingen tidligere erfaring er nødvendig. C# Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 3.

Hvor lang tid tar leksjonen «Grunnleggende robusthet: retry og backoff»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne C# Academy-leksjonen?

Ja. Alle C# Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. CancellationToken-mønstre og kooperativ kansellering
  2. Tidsavbrudd, IProgress og asynkrone disposables (emulering)
  3. Grunnleggende robusthet: retry og backoff
← Tilbake til C# Academy