L’architettura di microservizi ha guadagnato una significativa popolarità grazie alla sua scalabilità, flessibilità e natura modulare. Tuttavia, con più servizi indipendenti che comunicano su una rete, i guasti sono inevitabili. Una solida strategia di gestione del fallimento è fondamentale per garantire affidabilità, resilienza e un’esperienza utente senza soluzione di continuità.
In questo articolo, esploreremo diversi meccanismi di gestione dei fallimenti in microservizi e comprendere la loro importanza nella costruzione di applicazioni resilienti.
Perché la gestione dei fallimenti è importante nei microservizi?
Senza adeguati meccanismi di gestione dei guasti, questi guasti possono portare a interruzioni a livello di sistema, prestazioni degradate o addirittura tempi di inattività completi.
Gli scenari di fallimento si verificano comunemente a causa di:
- Guasti di rete (EG, problemi DNS, picchi di latenza)
- Servizio indisponibilità (advert es. Servizi dipendenti verso il basso)
- Interruzioni del database (EG, stanchezza del pool di connessioni)
- Picchi di traffico (advert es., carico elevato inaspettato)
In Netflix, se il servizio di raccomandazione è inattivo, non dovrebbe impedire agli utenti di streaming di video. Invece, Netflix si degrada con grazia visualizzando consigli generici.
Meccanismi di gestione dei fallimenti chiave nei microservizi
1. Meccanismo di riproduzione
A volte, i guasti sono temporanei (advert esempio, fluttuazioni di rete, brevi tempi di inattività del server). Invece di fallire immediatamente, un meccanismo di riproduzione consente al sistema di riaccendere automaticamente la richiesta dopo un breve ritardo.
Casi d’uso:
- Timeout di connessione del database
- Errori di rete transitoria
- Limiti di tasso API (advert es. Ritentare le chiamate API non riuscite dopo un periodo di recupero)
Advert esempio, il servizio di ordine di Amazon si rivolge a recuperare l’inventario da un database prima di contrassegnare un articolo come esaurito.
Greatest follow: Usa backoff esponenziale e jitter per prevenire le mandrie di tuono. Usando resilience4j Ritteni:
@Retry(identify = "backendService", fallbackMethod = "fallbackResponse")
public String callBackendService() {
return restTemplate.getForObject("http://backend-service/api/information", String.class);
}
public String fallbackResponse(Exception e) {
return "Service is presently unavailable. Please strive once more later.";
}
2. Sample interruttore
Se un microservizio non riesce costantemente, il tentativo di troppe volte può peggiorare il problema sovraccaricando il sistema. Un interruttore di circuito impedisce questo bloccando ulteriori richieste al servizio di fallimento per un periodo di recupero.
Casi d’uso:
- Prevenire guasti a cascata nei servizi di terze parti (advert es. Gateway di pagamento)
- Gestione degli errori di connessione del database
- Evitare il sovraccarico durante i picchi di traffico
Advert esempio, Netflix utilizza gli interruttori per evitare il sovraccarico di microservizi e richieste di reinserimento ai servizi di backup.
Stati usati:
- Chiuso → Chiamate consentite normalmente.
- Aprire → Le richieste vengono bloccate dopo più guasti.
- Mezzo apertura → Take a look at di richieste limitate per verificare il recupero.
Di seguito è riportato un esempio usando l’interruttore Avvio a molla (Resilience4j).
@CircuitBreaker(identify = "paymentService", fallbackMethod = "fallbackPayment")
public String processPayment() {
return restTemplate.getForObject("http://payment-service/pay", String.class);
}
public String fallbackPayment(Exception e) {
return "Fee service is presently unavailable. Please strive once more later.";
}
3. Timeout Gestione
Il servizio lento può bloccare le risorse, causando guasti a cascata. L’impostazione dei timeout garantisce che un servizio di fallimento non regga altri processi.
Casi d’uso:
- Impedire ai servizi lenti di bloccare i fili in applicazioni advert alto traffico
- Gestione dei ritardi dell’API di terze parti
- Evitare i impasse nei sistemi distribuiti
Advert esempio, i tempi di servizio di Uber emettono richieste se una risposta non viene ricevuta entro 2 secondi, garantendo che i ciclisti non attendono indefinitamente.
Di seguito è riportato un esempio di come impostare i timeout in Spring Boot (Restemplate e WebClient).
@Bean
public RestTemplate restTemplate() {
var manufacturing unit = new SimpleClientHttpRequestFactory();
manufacturing unit.setConnectTimeout(3000); // 3 seconds
manufacturing unit.setReadTimeout(3000);
return new RestTemplate(manufacturing unit);
}
4. Strategie di fallback
Quando un servizio è inattivo, i meccanismi di fallback forniscono risposte different invece di fallire completamente.
Casi d’uso:
- Mostrando dati memorizzati nella cache quando un servizio è inattivo
- Restituzione di raccomandazioni predefinite in un’app di e-commerce
- Fornire una risposta statica quando un’API è lenta
Advert esempio, YouTube fornisce video di tendenza quando i consigli personalizzati falliscono.
Di seguito è riportato un esempio per l’implementazione di fallback in Resilience4j.
@Retry(identify = "recommendationService")
@CircuitBreaker(identify = "recommendationService", fallbackMethod = "defaultRecommendations")
public Record getRecommendations() {
return restTemplate.getForObject("http://recommendation-service/api", Record.class);
}
public Record defaultRecommendations(Exception e) {
return Record.of("Fashionable Film 1", "Fashionable Film 2"); // Generic fallback
}
5. Modello di paratia
Modello di paratia isola i guasti limitando il consumo di risorse per servizio. Ciò impedisce la diffusione dei guasti attraverso il sistema.
Casi d’uso:
- Impedire a un servizio di fallimento di consumare tutte le risorse
- Isolamento di guasti nei sistemi multi-tenant
- Evitare le perdite di memoria a causa di un carico eccessivo
Advert esempio, il sistema di prenotazione di Airbnb garantisce che i servizi di prenotazione non consumano tutte le risorse, mantenendo operativa l’autenticazione dell’utente.
@Bulkhead(identify = "inventoryService", kind = Bulkhead.Sort.THREADPOOL)
public String checkInventory() {
return restTemplate.getForObject("http://inventory-service/inventory", String.class);
}
6. Filia di messaggi per elaborazione asincrona
Invece di chiamate di servizio dirette, utilizzare le code dei messaggi (Kafka, RabbitMQ) per disaccoppiarsi i microservizi, garantendo che i guasti non incidono sulle operazioni in tempo reale.
Casi d’uso:
- Microservizi di disaccoppiamento (servizio ordina → Servizio di pagamento)
- Garantire un’elaborazione affidabile basata su eventi
- Gestire i picchi di traffico con grazia
Advert esempio, le richieste di elaborazione dell’ordine di Amazon Code in Kafka per evitare guasti che incidono sul checkout.
Di seguito è riportato un esempio dell’uso di kafka per l’elaborazione degli ordini.
@Autowired
non-public KafkaTemplate kafkaTemplate;
public void placeOrder(Order order) {
kafkaTemplate.ship("orders", order.toString()); // Ship order particulars to Kafka
}
7. Sourcing eventi e sample saga
Quando una transazione distribuita fallisce, l’approvvigionamento di eventi garantisce che ogni passaggio possa essere ribaltato.
Le applicazioni bancarie utilizzano la saga per impedire che venga detratto se un trasferimento fallisce.
Di seguito è riportato un esempio di un modello di saga per le transazioni distribuite.
@SagaOrchestrator
public void processOrder(Order order) {
sagaStep1(); // Reserve stock
sagaStep2(); // Deduct stability
sagaStep3(); // Verify order
}
8. Registrazione e monitoraggio centralizzati
I microservizi sono altamente distribuiti, senza la registrazione e il monitoraggio adeguati, i guasti rimangono non rilevati fino a quando non diventano critici. In un ambiente di microservizi, i registri sono distribuiti su più servizi, contenitori e host.
Uno strumento di aggregazione del registro raccoglie i registri da tutti i microservizi in una singola dashboard, consentendo un rilevamento e una risoluzione di guasti più rapidi. Invece di conservare i registri separatamente per ciascun servizio, un aggregatore di tronchi raccoglie e centralizza i registri, aiutando i workforce advert analizzare i fallimenti in un unico posto.
Di seguito è riportato un esempio di registrazione dei microservizi utilizzando lo stack ELK (ElasticSearch, Logstash, Kibana).
logging:
degree:
root: INFO
org.springframework.net: DEBUG
Greatest follow per la gestione dei guasti nei microservizi
Progettazione per il fallimento
I guasti nei microservizi sono inevitabili. Invece di cercare di eliminare completamente i fallimenti, anticiparli e costruire resilienza nel sistema. Ciò significa progettare microservizi per recuperare automaticamente e ridurre al minimo l’impatto dell’utente quando si verificano guasti.
Scenari di fallimento del take a look at
La maggior parte dei sistemi è testata solo per i casi di successo, ma i guasti del mondo reale si verificano in modi inaspettati. L’ingegneria del caos aiuta a simulare i guasti per testare come i microservizi li gestiscono.
Grazioso degrado
In scenari advert alto traffico o guasti al servizio, il sistema dovrebbe dare la priorità alle caratteristiche critiche e degradare con grazia le funzionalità meno essenziali. Dai la priorità ai servizi essenziali rispetto a quelli non critici.
IDEMPOTENZA
Assicurarsi che i tentativi non duplicano transazioni. Se un microservizio si ritrova una richiesta a causa di un errore di rete o timeout, può accidentalmente creare transazioni duplicate (advert esempio, addebitare un cliente due volte). IdePotency garantisce che le richieste ripetute abbiano lo stesso effetto di una singola richiesta.
Conclusione
La gestione dei fallimenti nei microservizi non è facoltativo, è una necessità. Implementando tentativi, interruttori, timeout, paratie e strategie di fallback, è possibile creare microservizi resistenti e tolleranti ai guasti.