Patronen voor API-snelheidsbeperking en schaalbaarheid · Les

Idempotentie en retry-mechanismen

Ontwerp idempotente API-bewerkingen en implementeer intelligente retry-mechanismen om tijdelijke fouten netjes af te handelen zonder neveneffecten.

Les 2 van 412 stappen

Idempotentie en retry-mechanismen is een gratis Patronen voor API-snelheidsbeperking en schaalbaarheid-les op CoddyKit. Dit is les 2 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Patronen voor API-snelheidsbeperking en schaalbaarheid. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Patronen voor API-snelheidsbeperking en schaalbaarheid bevat in totaal 4 lessen.

Wat is idempotentie?

In gedistribueerde systemen kunnen bewerkingen soms mislukken of worden onderbroken. Idempotentie is een eigenschap van een bewerking waarbij meerdere keren uitvoeren hetzelfde resultaat oplevert als één keer uitvoeren.

Je kunt het vergelijken met herhaaldelijk op een aan-uitknop drukken. Als de bewerking echt idempotent is, verandert de eerste druk de status, maar veranderen volgende drukken (zonder een tussentijdse 'Uit') deze niet verder. De eindstatus blijft hetzelfde.

Waarom idempotentie belangrijk is

Idempotentie is cruciaal voor het bouwen van robuuste en betrouwbare API's, vooral bij netwerkproblemen of tijdelijke serverfouten.

  • Voorkomt dubbele acties: Als een aanvraag halverwege mislukt en de client deze opnieuw probeert, zorgt idempotentie ervoor dat de bewerking niet twee keer wordt uitgevoerd.
  • Garandeert gegevensconsistentie: Voorkomt dat dubbele records of onjuiste statuswijzigingen ontstaan.
  • Ondersteunt nieuwe pogingen: Het is een fundamenteel concept waarmee clients aanvragen veilig opnieuw kunnen proberen zonder ongewenste neveneffecten.

Idempotent versus niet-idempotent

Laten we kijken naar veelgebruikte HTTP-methoden en hun idempotentie:

  • GET: Altijd idempotent. Gegevens meerdere keren ophalen verandert ze niet.
  • PUT: Idempotent. Een volledige resource meerdere keren bijwerken leidt tot dezelfde eindstatus.
  • DELETE: Idempotent. Een resource meerdere keren verwijderen heeft hetzelfde effect als deze één keer verwijderen (de resource blijft verwijderd).
  • POST: Over het algemeen niet idempotent. Meerdere keren een nieuwe resource maken leidt meestal tot meerdere nieuwe resources.

Het gaat om het resultaat, niet om de actie zelf.

Idempotentiesleutels implementeren

Voor niet-idempotente bewerkingen zoals POST (bijvoorbeeld een bestelling maken of een betaling verwerken) kunnen we een idempotentiesleutel introduceren.

Dit is een unieke identifier (vaak een UUID) die door de client wordt gegenereerd en met de aanvraag wordt meegestuurd. De server gebruikt deze sleutel vervolgens om dubbele aanvragen binnen een bepaalde periode te detecteren en te negeren.

Idempotentiecontrole aan de serverzijde

Hier zie je conceptueel hoe een server met een idempotentiesleutel kan omgaan. De server controleert of de sleutel al voor die specifieke bewerking is verwerkt.

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class PaymentProcessor {

    private Map<String, Boolean> processedKeys = new ConcurrentHashMap<>();

    public String processPayment(String idempotencyKey, double amount) {
        if (processedKeys.containsKey(idempotencyKey)) {
            System.out.println("Duplicate request for key: " + idempotencyKey + ". Returning previous result.");
            return "Payment already processed for key " + idempotencyKey;
        }

        // Simulate payment processing
        System.out.println("Processing payment of $" + amount + " with key: " + idempotencyKey);
        try {
            Thread.sleep(100); // Simulate work
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        processedKeys.put(idempotencyKey, true);
        return "Payment successful for key " + idempotencyKey;
    }

    public static void main(String[] args) {
        PaymentProcessor processor = new PaymentProcessor();

        // First attempt with a key
        System.out.println(processor.processPayment("uuid-123", 100.00));

        // Retry with the same key (should be ignored)
        System.out.println(processor.processPayment("uuid-123", 100.00));

        // New request with a different key
        System.out.println(processor.processPayment("uuid-456", 50.00));
    }
}

Inleiding tot nieuwe pogingen

Zelfs met idempotente bewerkingen kunnen aanvragen nog steeds mislukken door tijdelijke problemen, zoals time-outs van het netwerk, overbelasting van de server of korte serviceonderbrekingen. Hier komen mechanismen voor opnieuw proberen van pas.

Een mechanisme voor opnieuw proberen voert een mislukte bewerking na een korte vertraging automatisch opnieuw uit. Het doel is om tijdelijke fouten te omzeilen en de betrouwbaarheid van API-aanroepen te verbeteren.

Basislogica voor opnieuw proberen

Het eenvoudigste mechanisme voor opnieuw proberen bestaat uit een vast aantal pogingen, met een constante vertraging tussen de pogingen. Hoewel dit eenvoudig is, kan het een herstellende service soms overbelasten als veel clients tegelijkertijd opnieuw proberen.

public class SimpleRetry {

    public static void makeApiCall() {
        int maxRetries = 3;
        int retryCount = 0;
        long delayMillis = 1000; // 1 second

        while (retryCount < maxRetries) {
            try {
                System.out.println("Attempt " + (retryCount + 1) + ": Making API call...");
                // Simulate an API call that might fail
                if (Math.random() > 0.6) { // 40% chance of success
                    System.out.println("API call successful!");
                    return; // Exit if successful
                } else {
                    throw new RuntimeException("Simulated API failure.");
                }
            } catch (RuntimeException e) {
                System.out.println("API call failed: " + e.getMessage());
                retryCount++;
                if (retryCount < maxRetries) {
                    try {
                        System.out.println("Retrying in " + delayMillis + "ms...");
                        Thread.sleep(delayMillis);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        System.out.println("Retry interrupted.");
                        break;
                    }
                }
            }
        }
        System.out.println("All retry attempts failed.");
    }

    public static void main(String[] args) {
        makeApiCall();
    }
}

Exponentiële vertraging

Om te voorkomen dat services worden overbelast en ze meer tijd krijgen om te herstellen, is exponentiële vertraging een betere strategie. Hierbij wordt de vertraging tussen opeenvolgende pogingen steeds groter.

De vertragingen kunnen bijvoorbeeld 1s, 2s, 4s, 8s enzovoort zijn. Hierdoor neemt de belasting op een service met problemen af en worden de nieuwe pogingen over een langere periode verspreid.

Vertraging met jitter

Zelfs met exponentiële vertraging kunnen veel clients nog steeds een probleem veroorzaken als ze mislukken en op exact dezelfde exponentiële intervallen opnieuw proberen. Ze kunnen dan allemaal tegelijkertijd de service belasten: het zogenaamde probleem van de 'donderende kudde'.

Jitter voegt een willekeurig element toe aan de vertraging. Hierdoor worden de nieuwe pogingen gelijkmatiger verspreid en worden gesynchroniseerde verkeerspieken voorkomen.

import java.util.Random;

public class ExponentialBackoffRetry {

    private static final Random random = new Random();

    public static void makeApiCallWithBackoff() {
        int maxRetries = 5;
        long baseDelay = 500; // milliseconds
        long maxDelay = 16000; // cap the delay at 16 seconds

        for (int retryCount = 0; retryCount < maxRetries; retryCount++) {
            try {
                System.out.println("Attempt " + (retryCount + 1) + ": Making API call...");
                // Simulate an API call that might fail
                if (Math.random() > 0.7) { // 30% chance of success
                    System.out.println("API call successful!");
                    return; // Exit if successful
                } else {
                    throw new RuntimeException("Simulated API failure.");
                }
            } catch (RuntimeException e) {
                System.out.println("API call failed: " + e.getMessage());
                if (retryCount < maxRetries - 1) {
                    long delay = baseDelay * (long) Math.pow(2, retryCount);
                    delay = Math.min(delay, maxDelay);
                    // Add jitter: random value between 0 and delay
                    long jitteredDelay = random.nextInt((int) delay);

                    try {
                        System.out.println("Retrying in " + jitteredDelay + "ms (base: " + delay + ")...");
                        Thread.sleep(jitteredDelay);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        System.out.println("Retry interrupted.");
                        break;
                    }
                }
            }
        }
        System.out.println("All retry attempts failed after " + maxRetries + " retries.");
    }

    public static void main(String[] args) {
        makeApiCallWithBackoff();
    }
}

Idempotentie en opnieuw proberen gecombineerd

Idempotentie en mechanismen voor opnieuw proberen vormen samen een krachtige combinatie voor het bouwen van veerkrachtige gedistribueerde systemen.

  • Opnieuw proberen handelt tijdelijke netwerk- of servicefouten af, waardoor de kans groter wordt dat een bewerking slaagt.
  • Idempotentie zorgt ervoor dat er geen schadelijke dubbele neveneffecten optreden wanneer een bewerking opnieuw wordt geprobeerd die in werkelijkheid al was geslaagd, maar waarvan de client geen bevestiging had ontvangen.

Samen stellen ze clients in staat om met vertrouwen API-aanroepen te doen, omdat tijdelijke problemen niet tot gegevensbeschadiging of onjuiste statussen leiden.

Controleer uw begrip

Welke van de volgende uitspraken over idempotentie en mechanismen voor opnieuw proberen zijn WAAR?

Samenvatting: robuuste API's

In deze les hebben we twee belangrijke concepten voor het bouwen van zeer schaalbare en veerkrachtige API's onderzocht:

  • Idempotentie: bewerkingen die hetzelfde resultaat opleveren wanneer ze één keer of meerdere keren worden uitgevoerd, wat essentieel is om dubbele neveneffecten te voorkomen.
  • Mechanismen voor opnieuw proberen: strategieën zoals exponentiële vertraging met jitter, waarmee clients tijdelijke fouten netjes kunnen afhandelen door aanvragen opnieuw uit te voeren met steeds langere, willekeurige vertragingen.

Door idempotentie te combineren met intelligente logica voor opnieuw proberen, kunt u API-interacties ontwerpen die robuust, betrouwbaar en bestand zijn tegen het onvoorspelbare karakter van gedistribueerde systemen.

Gratis beginnen

Leer Patronen voor API-snelheidsbeperking en schaalbaarheid met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
12
Lessen
48

Veelgestelde vragen

Is de les “Idempotentie en retry-mechanismen” gratis?

Ja — de volledige tekst van “Idempotentie en retry-mechanismen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Patronen voor API-snelheidsbeperking en schaalbaarheid wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Patronen voor API-snelheidsbeperking en schaalbaarheid bevat in totaal 4 lessen.

Wat leer ik in “Idempotentie en retry-mechanismen”?

Ontwerp idempotente API-bewerkingen en implementeer intelligente retry-mechanismen om tijdelijke fouten netjes af te handelen zonder neveneffecten. Je oefent met Patronen voor API-snelheidsbeperking en schaalbaarheid door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Patronen voor API-snelheidsbeperking en schaalbaarheid te beginnen?

Ervaring vooraf is niet nodig. Patronen voor API-snelheidsbeperking en schaalbaarheid op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 2 van 4.

Hoe lang duurt de les “Idempotentie en retry-mechanismen”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Patronen voor API-snelheidsbeperking en schaalbaarheid?

Ja. Elke les over Patronen voor API-snelheidsbeperking en schaalbaarheid bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Circuit breakers en bulkheads
  2. Idempotentie en retry-mechanismen
  3. Geo-distributed API's en disaster recovery
  4. Rate-based load shedding en backpressure
← Terug naar Patronen voor API-snelheidsbeperking en schaalbaarheid