come gestire / architect soa quando il servizio diventa non disponibile?

7

Supponiamo che io abbia un servizio di terze parti chiamato Cool.io che fornisce un'API RESTful, ma che spesso non funziona. Le mie applicazioni consumano quell'API, ma quando Cool.io va giù, la mia app non può davvero fare molto ... ma dovrebbe!

Dire che creo un proxy per Cool.io e questo proxy memorizza una copia dei dati di Cool.io e fornisce endpoint RESTful per la mia applicazione. Supponiamo che il mio proxy abbia un'affidabilità del 100% o, almeno, più di Cool.io. Supponiamo inoltre che il mio proxy non abbia problemi a diffondere PUT / POST a Cool.io, e nessun problema a ricevere lo stesso da Cool.io (in altre parole, non ci sono problemi di sincronizzazione dei dati tra il mio proxy e Cool.io).

Questo disaccoppia la dipendenza della mia applicazione da Cool.io, che va giù per tutto il tempo ... ma non disaccoppia il proxy dal servizio Cool.io. Di conseguenza, quando la mia applicazione modifica qualcosa sul proxy, i dati del proxy cambiano e tenta di inviare quella modifica a Cool.io.

Tuttavia, se Cool.io non funziona, la richiesta restituisce solo un errore di indisponibilità (o una connessione fallita).

Qual è il modo corretto di progettare qualcosa di simile? In che modo ragazzi come Amazon o Netflix disaccoppiano i loro servizi in modo tale che un'interruzione non influisce sul consumatore, o se lo fa, lo fa con grazia?

La coda dei messaggi è in ordine qui?

Esiste una soluzione più semplice rispetto alla creazione di un proxy per il servizio inaffidabile?

    
posta ybakos 25.05.2012 - 22:38
fonte

3 risposte

5

Penso che tu abbia risposto da solo: Message Queue. È necessario il proprio proxy per poter attendere il ritorno del servizio e quindi inviare nuovamente le richieste. Quindi, invia le richieste in coda. Chiedere al gestore code di eseguire regolarmente il ping del servizio per verificarne lo stato e inviare i messaggi dalla coda al suo termine. Non rimuovere il messaggio dalla coda finché non ricevi una risposta positiva che il servizio ha elaborato.

    
risposta data 25.05.2012 - 22:49
fonte
2

Dato che il tuo servizio richiede molta attenzione, l'utilizzo di un proxy di memorizzazione nella cache sembra una buona idea. Ma attenzione: più si tenta di mantenere la semantica del sistema originale quando il back-end non funziona, più il sistema diventa complesso. E di solito, più sono sorprendenti le sue modalità di fallimento per l'utente finale. Entrambi questi fattori spesso motivano la decisione di adottare un semplice proxy di sola lettura.

Anche un proxy di sola lettura dovrebbe restituire un timestamp con i dati, per indicare quando i dati erano freschi. Per HTTP puoi codificare questo con IMS o un Etag; per altri sistemi dipenderà dal protocollo che stai utilizzando. Rifiutare di servire molto i dati unfresh dal proxy è una scelta che potresti non dover fare.

Nel tuo livello di applicazione, dovrai decidere cosa fare quando l'utente vuole eseguire un'azione simile a una mutazione sui dati di età T secondi.

Penso che normalmente sia meglio accettare la modifica e restituire un errore se il back-end (Cool.io) non ha elaborato la richiesta. Se si sceglie di rifiutare senza provare, si avranno problemi in cui il controllo pre-mutation trova il back-end in uno stato, ma il tentativo di applicare effettivamente la modifica lo trova in un altro - questa situazione è difficile da testare nel vostro sistema di regressione del sistema, quindi il mio consiglio è di non costruire un sistema che cerchi di farlo.

Se il back-end non può applicare la tua modifica, il tuo sistema potrebbe considerare questo errore come finale o potrebbe offrire di provare ad applicare la modifica quando il servizio ritorna.

Come ottimizzazione dell'esperienza utente, quando si sa che il proxy non è stato in grado di ottenere il servizio dal back-end, è possibile visualizzare avvisi sull'interfaccia utente, in modo che l'utente possa evitare una voce di data che richiede molto tempo per trovare il back-end non funziona.

Se offri di applicare una modifica non riuscita in un secondo momento, le modifiche che l'utente voleva applicare ma che non potevano essere applicate a breve avrebbero bisogno di essere archiviate. È possibile memorizzarli in una coda, ma come indicato da @mathew-flynn, sarà necessario gestire le modifiche in coda duplicate (forse in conflitto). Quindi probabilmente dovrai "accodare" le modifiche in modo interrogabile. Come in una tabella di database di modifiche non riconciliate. La cosa semplice da fare è rifiutare le modifiche ai dati che non sono state applicate al back-end. In caso contrario, l'impossibilità di applicare una determinata modifica al back-end potrebbe richiedere la revoca di più di una modifica a livello di utente.

Se è possibile che una modifica in coda non si applichi, è necessario fornire alcuni tipi di funzionalità in cui l'utente riconcilia le modifiche non riuscite.

Un caso particolarmente interessante è dove il backend è appena arrivato e un altro utente ha presentato una modifica in conflitto, dal vivo. Cioè, un nuovo cambiamento ha "superato" un cambiamento accodato. Si potrebbe prendere in considerazione il blocco di tutte le modifiche da parte degli utenti in caso di modifiche in attesa in coda. Un modo per ottenere questo è che tutte le modifiche, in diretta o differita, utilizzino la stessa coda. Se lo fai, sii molto sicuro che le modifiche ai problemi non possono rimanere bloccate in testa alla coda.

Come noterai da quanto sopra, tutto questo chiaramente richiede cambiamenti nella semantica dell'applicazione. Non puoi semplicemente farlo invisibilmente in un livello proxy, a meno che tu non rifiuti le mutazioni che non possono essere applicate immediatamente al back-end. E se fa la differenza per l'utente se i dati sono freschi o meno, potrebbe essere necessario avvisarli che stanno guardando i dati non aggiornati.

Hai anche chiesto in che modo i grandi servizi si occupano di questo. Uno dei modi più popolari è che i backend siano resi più chiari da user-id in modo che se una determinata parte del servizio è inattiva, solo alcuni utenti ne sono interessati. Questo è facile da fare per cose come il servire dati statici (che per la maggior parte non interessa chi sei) ma molto più difficile per i servizi in cui gli utenti hanno relazioni N-to-N (ad esempio cose come Twitter - anche se nel caso di Twitter le complessità attorno alle mutazioni fallite sono per lo più assenti).

    
risposta data 27.05.2012 - 19:26
fonte
0

I tuoi servizi dovrebbero essere autonomi e dovrebbero comunicare tra loro tramite messaggi basati sugli eventi. Oltre a utilizzare una soluzione basata sulla coda, i tuoi dati dovrebbero essere decentralizzati. Ed evitare l'orchestrazione del servizio.

Per ottenere ciò con la minima quantità di dolore, decomponi il tuo sistema in servizio lungo il tuo business-capacità . Ci sono diversi modi per identificarli, ma probabilmente quello più semplice è trattare i tuoi servizi come passi che la tua azienda dovrebbe attraversare al fine di ottenere un valore aziendale. Ecco un esempio di utilizzo di questa tecnica.

    
risposta data 14.11.2017 - 20:19
fonte

Leggi altre domande sui tag