2015-11-11 15 views
6

Ho una situazione seguente.
Possiedo un client REST che funge da facciata verso altri 3 client REST. (Sto programmando in Java, utilizzando Spring Boot)Come rendere transazionali/atomici più richieste REST?

Una delle responsabilità del client include l'esecuzione di operazioni CRUD sugli utenti.
Ora, tutti gli altri 3 sistemi che espongono le proprie API REST hanno una sorta di gestione degli utenti.

Quando ricevo una richiesta, ad esempio, per creare un utente, devo crearli su quei 3 sistemi tramite le API REST e persistere nel mio database.

Ora, nel migliore dei casi, ho appena chiamato le loro API, inserire l'utente nel mio DB e tutto è perfetto.

Tuttavia, considerare lo scenario in cui la creazione di utenti supera solo 1 servizio esterno. Riprovare l'operazione su tutti gli altri? Cerco di eliminare l'utente su quelli che ha superato?

Qual è il modo corretto per farlo?

+2

Prova a considerare l'intera transazione come una risorsa. – chrylis

risposta

2

Non c'è un modo semplice per farlo. Se una qualsiasi parte della "transazione" non riesce, non è possibile eseguire il rollback o riprovare in modo affidabile per garantire la coerenza su tutti i sistemi. Avresti bisogno di una stretta integrazione con tutti e tre (quattro sistemi) per utilizzare un sistema di transazioni distribuito.

1

Un modo per farlo (supponendo che si può tollerare diversi stati tra i nodi):

  1. Diciamo, la tua facciata ha persistente coda di richieste in arrivo CRUD. Una volta che la nuova richiesta req è in coda, si inizia a chiedere ai client REST di eseguirla;
  2. Una volta che tutti i client REST hanno eseguito la richiesta e segnalato il successo, è possibile rimuoverlo dalla coda e rendere questa modifica effettiva allo stato globale del sistema. Ad esempio, se req era CREATE, il nuovo utente è visibile al mondo esterno, se req è aggiornato, quindi gli aggiornamenti diventano visibili al mondo esterno e così via. Ciò implica che lo stato globale è ciò che è memorizzato nel database del sistema di facciata;
  3. Ora, che cosa fare se la facciata viene interrotta mentre req è in corso (non tutti i client REST hanno riportato risultati positivi)? La facciata, dopo il riavvio, deve prendere tutte le richieste in sospeso dalla coda (persistente) e inviarle ai client REST. Ciò implica che i client REST possono rilevare se hanno già elaborato quella particolare richiesta (ed è appena successo, la facciata non ha elaborato la risposta prima che scendesse). Solitamente, ciò viene ottenuto utilizzando l'ID di richiesta univoco, ad esempio UUID.

Sopra il processo funziona se è sicuro che il sistema abbia una richiesta elaborata solo da parte dei client REST (ciò significa che i dati sono accessibili al mondo esterno solo tramite facciata). In caso contrario, è necessario un sistema che supporti le transazioni distribuite (google per il commit a due fasi).

1

Avrete bisogno di affrontarlo caso per caso. Nell'esempio che hai fornito, puoi provare ad eliminare, ma potrebbe anche non riuscire.

Una volta che hai un fallimento è necessario:

  1. Maniglia tentativi di creare l'utente
  2. clienti maniglia che potrebbero accedere a un utente anche se solo 1 su 3 è stato creato

Per riprovare, è possibile fare in modo che l'inizializzatore riprovi o accodare le richieste.

In entrambi i casi è probabile che si desideri progettare l'API in modo tale che se si tenta di ricreare un utente già creato, verrà considerato come un aggiornamento.

Ad esempio, solo uno dei tre è riuscito.

La pagina Web che avvia la richiesta restituisce un errore. L'utente riprova. Questa volta aggiorni il primo e riprova creando il 2 ° e il 3 °.

Per clienti Ricerca di record e ottenere un utente parziale, potrete sia bisogno di un quarto sistema di record che tenga traccia quali sono stati creati, o gli stessi clienti avranno bisogno di vedere che solo 1 su tre è stato creato. Questo potrebbe non essere nemmeno un problema se i tuoi clienti guardano sempre uno dei tre alla volta.

Problemi correlati