Rest API Architecture from Rest in Practice book

1

Manteniamo un'API che come parte del suo scopo effettua una chiamata a un'API esterna. Questa API esterna impiega alcuni secondi per soddisfare la richiesta che facciamo. Con la nostra architettura attuale la richiesta viene effettuata in modo sincrono, il che significa che la risposta http che restituiamo alla richiesta dell'utente viene bloccata finché il nostro servizio non riceve la risposta dall'API esterna.

Sto pensando di cambiare la nostra architettura per essere in grado di gestire la richiesta in modo asincrono ... Con questo intendo accettare la richiesta dell'utente nella nostra API e mettere un messaggio in coda in modo da restituire una risposta http molto più veloce. La risposta conterrebbe l'indirizzo di dove è possibile trovare il risultato completo / completo. Un'attività in background dovrebbe quindi prelevare i messaggi dalla coda ed effettuare la chiamata all'API esterna, quindi archiviare il risultato all'indirizzo fornito nella nostra risposta. L'indirizzo può quindi essere interrogato dall'utente / client fino a quando viene raggiunto lo stato desiderato della respregazione (cioè quando l'attività in background ha terminato di chiamare l'api esterna e ha memorizzato il risultato).

Questa architettura mi è stata principalmente rimossa dal libro REST in Practice. Il punto cruciale è che la nostra API esterna impiega solo 2-3 secondi per restituire la risposta. L'esempio nel libro descrive un processo di ordinazione che potrebbe richiedere minuti o ore. Questa soluzione suggerita vale l'aumento di complessità per un tempo di risposta così breve dalla nostra dipendenza esterna? Ad esempio, l'applicazione continuerà a scalare con l'architettura sincrona esistente?

    
posta Nick 17.07.2013 - 12:34
fonte

3 risposte

2

La situazione che stai descrivendo (usando code e polling) funzionerà sicuramente, ma finché la tua API esterna impiegherà solo pochi secondi per restituire una risposta, penso che ci sia un modo più semplice:

Come hai descritto, è consigliabile che la risposta della tua pagina web non includa i dati dell'API esterna, poiché ciò consente di inviare la risposta della pagina più rapidamente. Effettuerò la chiamata all'API esterna come segue:

  • La pagina di risposta contiene una parte di javascript che effettua una chiamata AJAX asincrona a un endpoint REST sul tuo sito web.
  • L'endpoint REST chiama l'API esterna e blocca solo fino a quando non riceve la risposta. Una volta ricevuta la risposta, restituisce i risultati al chiamante (ovvero il browser che ha eseguito la chiamata AJAX).
  • Quando la pagina di risposta javascript riceve i dati dalla chiamata AJAX, visualizza i risultati manipolando il DOM HTML della pagina di risposta.

In questo modo, l'unica cosa che deve essere asincrona è la chiamata AJAX dal browser; questo avvia effettivamente un nuovo "thread in background" e le chiamate che vengono eseguite in questo thread (dal browser, all'endpoint REST, all'API esterna e quindi di nuovo indietro) possono essere eseguite in modo sincrono.

Ovviamente, funziona solo finché l'API esterna restituisce le risposte abbastanza velocemente (meno di un minuto), altrimenti le chiamate sincrone scadranno. Finché sei sicuro che questo è il caso, penso che questa soluzione sia meno complicata e soddisfi comunque i tuoi requisiti.

    
risposta data 27.07.2014 - 12:13
fonte
1

Non c'è nulla in REST che ti impedisca di combinare soluzioni sincrone e asincrone per combinazione di risorse e metodi.

Ad esempio, nel nostro server di query restituiamo quasi tutto in modo sincrono poiché le risorse / informazioni sono facilmente disponibili. Solo quando viene pubblicata una nuova query, passiamo alla route della generazione di un identificatore e restituiamo una risposta "Accepted" o "See other" (303) con l'URI della risorsa dei risultati della query nel corpo e l'intestazione della posizione. La restituzione delle informazioni sulla query e i risultati della query stessi viene eseguita di nuovo in modo sincrono.

update

Non sono presenti numeri sul ritardo medio prima che i dati dei risultati siano disponibili per una query pubblicata. Stiamo ancora lavorando all'implementazione di REST. Tuttavia, le query nella nostra architettura corrente richiedono di solito millisecondi (siamo una sorta di database in memoria), sebbene abbiamo clienti in cui alcune query sono noti per richiedere 20 minuti per restituire un risultato. Quindi, in un certo senso, il bisogno di asincronismo non è tanto il ritardo medio, ma il fatto che non vogliamo avere alcuna richiesta che possa bloccare una connessione per un periodo di tempo serio (> 1 secondo o giù di lì) e clienti puoi pubblicare query che vengono eseguite per un numero superiore.

Per fornire altri dettagli sull'esecuzione asincrona delle query:

  • Il "risultato della query" è una risorsa che contiene le nozioni di base sui risultati di una query pubblicata: identificatore, stato (avanzamento), uri per i dati dei risultati (vuoto / assente fino a che non è disponibile), questi tipi di cose.
  • La nuova risorsa "risultato query" viene archiviata immediatamente e prima che venga restituita la risposta al POST.
  • Il processo di query aggiorna il "risultato della query" con il suo stato di avanzamento e, infine, con il numero totale di righe nei dati dei risultati.

In altre parole: la nuova risorsa "risultato query" è interrogabile non appena viene restituito il POST. Non è ancora completo. Il polling del risultato della query mostrerà lo stato e l'avanzamento e una volta terminato il processo di query, lo stato sarà terminato e l'uri per i dati del risultato avrà un valore.

    
risposta data 17.07.2013 - 12:51
fonte
0

Se vuoi davvero separare per qualsiasi motivo il flusso di lavoro corrente da dove viene presentato il risultato, potresti usare links -section in JSON-Response.

{
    "name": "currentStep",

    ...

    "links": [ {
        "rel": "self",
        "href": "/api/job/currentStep"
    },
    {
        "rel": "previousStep",
        "href": "/api/job/previousStep"
    },
    {
        "rel": "result",
        "href": "/api/job/result"
    }
     ]
}

Questo indica dove sei ora , dove eri prima e dove il risultato è sarà . Implementandolo in questo modo, segnali la tua intenzione, che il risultato è in una posizione diversa. Quindi il problema di in attesa del passaggio corrente per i risultati è risolto.

Ciò che non è coperto da questa soluzione è il problema, che né tu né l'utente della tua API sai, se ci sono risultati o quando i risultati saranno essere disponibile sotto l'URL indicato. Quindi il tuo problema generale non è risolto, è solo rinviato. Quando viene richiamato l'URL (nel mio esempio / api / job / result ), non è sicuro se ci sia o meno un risultato.

Da un lato, hai un servizio sincrono , che dura in media 2-3 secondi , dopo di che il risultato viene restituito all'utente senza interruzione del flusso o d'altra parte un spazio possibile ma una risposta immediata.

Senza ulteriore conoscenza dell'architettura generale e della tua base utente è difficile dire qualcosa. Quanto critico è 2-3 secondi ? Nel settore finanziario potrebbe essere mission-critical in altri settori potrebbe essere trascurabile.

Un'altra soluzione mi viene in mente, ma per questo, devo conoscere meglio la tua infrastruttura applicativa:

Se sono necessarie più chiamate di servizio , potresti renderle tutte asincrone. Supponiamo di avere la seguente configurazione:

Per completare l'intera richiesta devi fare i passi A, B.C e D. D in questo caso è la chiamata al servizio esterno, che richiede 2-3 secondi. Quindi, se li fai tutti in ordine, hai il passo A prendendo 0,5, B 0,5 e C 0,5 s. Quello è 1.5s. A cui sono stati aggiunti i 2 della chiamata D . Ciò fa aspettare 3,5 anni.

Se li fai tutti in parallelo , devi solo aspettare il più lento. In questo caso, sarebbe 2s che è significativamente più veloce.

Per non parlare di long-polling / comet ("oldschool") o websockets . Ad es. websockets hai la possibilità di spingere il risultato dal server in pipe non appena lo hai.

    
risposta data 27.07.2014 - 16:05
fonte

Leggi altre domande sui tag