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