Come progettate il vostro software che aggiorna diversi microservizi, se uno di questi fallisce?


12

Esiste un modello o pratica di progettazione che posso usare per aiutare con servizi che sono inattivi o inattivi, mentre altri sono stabili?

Cosa succede se ho tre microservizi e due di loro sono buoni e uno muore proprio nel mezzo di un POST? Due riceveranno il POST e uno no. Non credo di poter effettuare transazioni perché sto spedendo le mie richieste a un servizio.

Come posso progettare per questo? Non voglio dati orfani in vari database.


6
Non è un problema semplice da risolvere. L'ho visto implementato come una coda per i servizi (eventuale coerenza), poiché molto probabilmente, il tuo non avere il controllo dei servizi e l'imposizione di gestori di transazioni o capacità transazionali è nella migliore delle ipotesi, e probabilmente non è una buona idea in un ambiente SOA. L'ho visto principalmente nel push mobile, dove potresti avere o meno una connessione con la tua destinazione.
Mike,

L'acido rispetto ai microservizi è un dado difficile da decifrare, un'altra opzione potrebbe essere una sorta di bus, usando redis publishing / iscriviti o un progetto di coda e pubblica una volta dal canale in entrata, quindi i tuoi servizi di abbonamento o proxy di servizio spingono verso gli obiettivi e segnalano il successo fallimento. Dovrai monitorare i guasti e avere un flusso anche per questo. Puoi anche avere errori in cui la transazione non è valida su un servizio ma valida su altri due ma è solo un altro flusso di errori che dovrai affrontare.
Tim Cederquist,

Non usare qualcosa come "gestore code", che è ciò che immagino che Redis causerebbe un collo di bottiglia? O almeno hai anche un alto potenziale? Non conosco altro che tu abbia descritto.
Johnny,

A seconda del volume del flusso di dati, ho implementato un gestore code, che riprova le trasmissioni fino a quando non viene segnalato il successo o pubblica una notifica non riuscita e invia un avviso SMS sull'interruzione. Immagino che dipenda un po 'anche dalla finestra di interruzione prevista (per quanto tempo).
h11 11

È a questo che serve qualcosa come rabbitmq?
johnny,

Risposte:


9

Alcune opzioni.

Utilizzare un canale di comunicazione persistente

Invece di HTTP, rilascia i messaggi in una coda altamente disponibile e persistente. Ad esempio Kafka. Finché il server di destinazione diventa disponibile a un certo punto, riceverà il messaggio.

Ora hai il compromesso del provisioning e della gestione di un sottosistema complesso (la coda). Quindi assicurati di analizzare se questo vale la pena.

Backoff e riprovare

Chiedi al chiamante di conservare la richiesta non riuscita (possibilmente persistente su disco) e riprovare periodicamente. In questo caso è importante distinguere tra la tua richiesta causando un arresto anomalo e il servizio inattivo. Il primo è probabilmente dovuto a un bug e dovrebbe essere registrato ... probabilmente i tentativi non faranno la differenza fino a quando non verrà effettuata una correzione.

Rileva e compensa

Un'attività periodica verifica le condizioni di coerenza tra i microservizi. Ad esempio, gli errori vengono registrati fino alle richieste API dirette, se necessario. Se rileva un problema (ad es. C'è un ordine ma la spedizione non ha mai ricevuto l'elenco di imballaggio), fai i passaggi di compensazione. Tali passaggi potrebbero essere la creazione di un ticket di supporto per una correzione manuale o l'invio tramite e-mail di qualcuno o altro.

Prendi in considerazione le alternative di progettazione

Un caso come questo probabilmente richiede un gateway API per gestire le chiamate ai microservizi interessati. In questo modo controlli quali tattiche vengono utilizzate per mitigare questo problema. Probabilmente non vorrai caricare i clienti con quei dettagli di implementazione. Vedi il modello dell'interruttore .

Poiché i microservizi sono indipendenti, esiste sempre qualche caso di errore che può causare incoerenze. Devi essere pronto a fare correzioni manuali quando si presentano.

Se si richiede una forte coerenza, i microservizi non saranno adatti. Se hai ancora bisogno di scalabilità, potresti voler esaminare il sharding in cui i dati correlati possono essere collocati nello stesso frammento per garanzie di coerenza. Puoi comunque ridimensionare IO aggiungendo frammenti.

Se hai bisogno di una forte coerenza e non hai problemi di scalabilità, usa semplicemente i servizi monolitici. Utilizzare le librerie come limiti all'interno dell'applicazione per separare le preoccupazioni.


È a questo che serve RabbitMQ?
Johnny,

RabbitMQ è la risposta alla tua domanda? No. Potrebbe far parte di una soluzione che soddisfa le tue esigenze, ma non risolverà il problema da solo.
Kasey Speakman,

Solo una nota. Penso che RabbitMQ non persista i messaggi. Viene consumato e rimosso dalla coda, quindi NO. Se hai bisogno di persistenza e riprova, RabbitMQ non ti aiuterà.
Laiv

2

Penso che quello che stai descrivendo sia il problema del consenso: non vuoi impegnarti a meno che ogni partecipante alla transazione distribuita non dica che l'operazione è andata a buon fine. La soluzione semplice a questo è il Two Phase Commit. Essenzialmente, mette in scena la transazione in ciascun sistema fino a quando ognuno non ripete che la stadiazione ha avuto successo (Fase 1). Se ogni partecipante alla transazione restituisce successo, a ciascuno viene detto di impegnarsi; se invece uno di essi ha restituito un errore, viene emesso un rollback (Fase 2). C'è una ruga in questo che ti porta alla più complessa soluzione Commit trifase. Puoi leggere una descrizione molto migliore di ciascuno qui:

http://the-paper-trail.org/blog/consensus-protocols-two-phase-commit/

http://the-paper-trail.org/blog/consensus-protocols-three-phase-commit/

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.