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
- 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.
- 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.
- 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.
Curs de Microserveis
Mòdul 1: Introducció als Microserveis
- Conceptes Bàsics de Microserveis
- Avantatges i Desavantatges dels Microserveis
- Comparació amb Arquitectura Monolítica
Mòdul 2: Disseny de Microserveis
- Principis de Disseny de Microserveis
- Descomposició d'Aplicacions Monolítiques
- Definició de Bounded Contexts
