La gestió d'errors i la recuperació són components crítics en l'arquitectura de microserveis. A causa de la naturalesa distribuïda dels microserveis, els errors poden ocórrer en qualsevol punt de la xarxa, i és essencial dissenyar sistemes que puguin gestionar aquests errors de manera eficient i recuperar-se d'ells per mantenir la disponibilitat i la fiabilitat del sistema.

Conceptes Clau

  1. Tipus d'Errors

  • Errors de Xarxa: Problemes de connectivitat, latència elevada, pèrdua de paquets.
  • Errors de Servei: Fallades en un microservei específic, com ara caigudes del servei, errors de lògica, excepcions no controlades.
  • Errors de Dependència: Fallades en serveis externs o altres microserveis dels quals depèn el servei actual.

  1. Estratègies de Gestió d'Errors

  • Retry (Reintents): Tornar a intentar una operació fallida després d'un cert interval de temps.
  • Circuit Breaker: Tallar les connexions a un servei fallit per evitar sobrecarregar-lo amb sol·licituds fallides.
  • Fallback: Proporcionar una resposta alternativa o degradada quan un servei no està disponible.
  • Timeouts: Establir límits de temps per a les operacions per evitar esperes indefinides.

  1. Patrons de Recuperació

  • Bulkhead (Compartimentació): Aïllar diferents parts del sistema per evitar que una fallada en una part afecti tot el sistema.
  • Failover: Redirigir el trànsit a un servei de reserva en cas de fallada del servei principal.
  • Graceful Degradation: Permetre que el sistema continuï funcionant amb funcionalitat reduïda en cas de fallada.

Implementació Pràctica

Retry (Reintents)

Exemple en Java amb Spring Retry

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Retryable(
        value = {RemoteServiceException.class},
        maxAttempts = 5,
        backoff = @Backoff(delay = 2000)
    )
    public String callRemoteService() throws RemoteServiceException {
        // Lògica per cridar el servei remot
        return remoteService.call();
    }
}

Circuit Breaker

Exemple en Java amb Resilience4j

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @CircuitBreaker(name = "myService", fallbackMethod = "fallback")
    public String callRemoteService() {
        // Lògica per cridar el servei remot
        return remoteService.call();
    }

    public String fallback(Throwable t) {
        // Lògica de fallback
        return "Fallback response";
    }
}

Fallback

Exemple en Java amb Hystrix

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @HystrixCommand(fallbackMethod = "fallback")
    public String callRemoteService() {
        // Lògica per cridar el servei remot
        return remoteService.call();
    }

    public String fallback() {
        // Lògica de fallback
        return "Fallback response";
    }
}

Timeouts

Exemple en Java amb OkHttp

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

public class MyService {

    private final OkHttpClient client;

    public MyService() {
        this.client = new OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .writeTimeout(10, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .build();
    }

    public String callRemoteService() throws IOException {
        Request request = new Request.Builder()
            .url("http://remote-service-url")
            .build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }
}

Exercicis Pràctics

Exercici 1: Implementar Retry

Descripció: Implementa una funcionalitat de retry per a un servei que pot fallar de manera intermitent.

Requisits:

  • Utilitza Spring Retry.
  • Configura el servei per intentar fins a 3 vegades amb un interval de 1 segon entre intents.

Solució:

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

@Service
public class MyRetryService {

    @Retryable(
        value = {RemoteServiceException.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000)
    )
    public String callRemoteService() throws RemoteServiceException {
        // Lògica per cridar el servei remot
        return remoteService.call();
    }
}

Exercici 2: Implementar Circuit Breaker

Descripció: Implementa un circuit breaker per a un servei que pot fallar de manera intermitent.

Requisits:

  • Utilitza Resilience4j.
  • Configura el circuit breaker per obrir-se després de 5 fallades consecutives i tancar-se després de 10 segons.

Solució:

import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.stereotype.Service;

@Service
public class MyCircuitBreakerService {

    @CircuitBreaker(name = "myService", fallbackMethod = "fallback")
    public String callRemoteService() {
        // Lògica per cridar el servei remot
        return remoteService.call();
    }

    public String fallback(Throwable t) {
        // Lògica de fallback
        return "Fallback response";
    }
}

Errors Comuns i Consells

Errors Comuns

  • No configurar correctament els intervals de retry: Això pot portar a sobrecarregar el servei fallit.
  • No implementar timeouts: Això pot causar que les sol·licituds quedin penjades indefinidament.
  • No tenir un mecanisme de fallback: Això pot causar que el sistema falli completament en cas de fallada d'un servei.

Consells

  • Monitoritzar els patrons de retry i circuit breaker: Això ajuda a identificar problemes recurrents i ajustar les configuracions.
  • Utilitzar eines de monitoratge i logging: Això permet detectar i diagnosticar errors de manera més eficient.
  • Provar els mecanismes de gestió d'errors: Assegura't que els teus mecanismes de retry, circuit breaker i fallback funcionen correctament sota diferents condicions de fallada.

Conclusió

La gestió d'errors i la recuperació són fonamentals per a la robustesa i la fiabilitat dels sistemes basats en microserveis. Mitjançant l'ús de patrons com retry, circuit breaker, fallback i timeouts, es pot assegurar que els serveis siguin capaços de gestionar errors de manera eficient i mantenir la disponibilitat del sistema. Els exercicis pràctics proporcionats ajuden a consolidar aquests conceptes i a aplicar-los en situacions reals.

© Copyright 2024. Tots els drets reservats