2016-07-10 42 views
7

Supponiamo che stiate progettando un'API REST su HTTP per una "stanza" server in cui i clienti sottoscrittori desiderano monitorare gli eventi pubblici che si verificano nella stanza (ad esempio un nuovo partecipante si unisce alla stanza , un altro lascia la stanza, e così via ...) facendo lunghe richieste di voto.Implementazione di risposte lato server a polling lungo tramite API REST

Qual è il modo migliore per implementare questo da un punto di vista lato server in modo che il client non perderà alcun evento tra i sondaggi consecutivi? Ad esempio, il server dovrebbe implementare una coda di eventi che devono esistere nella coda fino a quando tutti gli abbonati li hanno ottenuti?

Esistono tutorial, esempi, alcune nozioni teoriche su Internet sulla progettazione di tale API e tutte le cose che dovrebbero essere prese in considerazione dal punto di vista del server?

+0

Per curiosità, perché si desidera utilizzare HTTP e polling lungo? Il tuo amministratore di sistema/gestore ti sta forzando? Perché questo è molto più facile da implementare usando websockets. –

+0

sì, in qualche modo "forzare", diciamo che è un requisito – Martin

+0

Che ne dici di ajax inverso? – asprin

risposta

1

Risposta molto breve - perché non usare solo EventStore?

Risposta breve: perché non utilizzare Evento Store come reference implementation e adattare their solution in modo che corrisponda ai vincoli di implementazione?

Qual è il modo migliore per implementare questo da un punto di vista lato server in modo che il client non perderà alcun evento tra i sondaggi consecutivi? Ad esempio, il server dovrebbe implementare una coda di eventi che devono esistere nella coda fino a quando tutti gli abbonati li hanno ottenuti?

REST offre di per sé alcune linee guida. Non dovrebbe esserci stato di applicazione memorizzato sul server; il messaggio inviato dal client deve includere qualsiasi stato lato client (come la posizione corrente nel flusso di eventi) che il server dovrà soddisfare la richiesta. La risorsa identificata nella richiesta è un'astrazione - quindi il client può inviare messaggi a, ad esempio "l'evento che viene dopo l'evento 7", che ha senso anche se il prossimo evento non esiste ancora. L'interfaccia uniforme deve essere rispettata, per consentire il ridimensionamento tramite cache e simili che sono al di fuori del controllo del server. La rappresentazione dello stato della risorsa deve essere ipermediale, con controlli che consentono al client di avanzare dopo aver consumato i messaggi attualmente disponibili.

HTTP lancia in alcuni più specifici. Poiché non vi è tracciamento dello stato del client sul server, la lettura dalla coda è un'operazione sicura. Pertanto, uno dei metodi sicuri HTTP (GET, per essere precisi) dovrebbe essere utilizzato per la lettura. Poiché GET in realtà non supporta il corpo del contenuto nella richiesta, le informazioni necessarie al server devono essere tutte inserite nell'intestazione della richiesta.

In altre parole, l'URI viene utilizzato per specificare la posizione corrente del client nel flusso di eventi.

Atom Syndication fornisce un buon formato ipermediale per l'elaborazione degli eventi: il flusso degli eventi si associa a un feed, la mappa degli eventi alle voci.

Di per sé, questi pezzi offrono un grande vantaggio in un processore di eventi conforme ai vincoli architetturali REST. Si solo necessario eseguire il polling lungo su di esso.

Per avere un'idea di come è possibile implementare il polling lungo per conto proprio, è possibile dare un'occhiata allo ticketing demo, scritto da Michael Barker (manutentore dello LMAX Disruptor).

La trama di base nella demo di Michael è che un singolo thread di writer sta monitorando (a) tutti i client che attualmente stanno aspettando un aggiornamento e (b) la cache locale di eventi.Tale thread legge un batch di eventi, identifica le richieste che devono essere notificate, risponde a ciascuna di tali richieste a turno e quindi avanza per elaborare il successivo batch di eventi.

Tendo a considerare la cache locale degli eventi come un buffer circolare (come il disturbatore stesso, ma privato del thread dello scrittore). Il thread writer conosce (dalle informazioni nella richiesta HTTP) la posizione di ciascun client nel flusso di eventi. Confrontando questa posizione al puntatore corrente nel buffer circolare, ogni richiesta in sospeso può essere classificato ha

Lontano Passato La posizione che il cliente chiede è già stato sfrattato dalla cache. Reindirizza il client a una copia persistente "fredda" di quella posizione nello stream, dove può seguire i controlli hypermedia per raggiungere il presente.

Ultimo passato La posizione che il client sta cercando è attualmente disponibile nella cache, quindi genera immediatamente una risposta al client con gli eventi disponibili e invia tale risposta.

Vicino al futuro La posizione che il client sta cercando non è disponibile nella cache, ma lo scrittore prevede di essere in grado di soddisfare tale richiesta prima che scada lo SLA. Quindi parcheggiamo il cliente fino a quando non arrivano altri eventi.

Far futuro La posizione che il cliente sta cercando non è disponibile nella cache, e noi Non anticipare che saremo in grado di soddisfare la richiesta nel tempo a disposizione. Quindi rispondiamo ora e lasciamo che il cliente decida cosa fare.

(Se si ottiene un numero sufficiente di client di polling che è necessario iniziare a ridimensionare il server di polling lungo, è necessario considerare il caso in cui tali server non sono sincronizzati e un client viene indirizzato da un server veloce a uno che ha In questo modo vorrai avere una strumentazione che ti consenta di tenere traccia di quanto spesso stia accadendo, in modo da poter applicare il rimedio appropriato).

Ci sono anche alcuni casi limite da considerare - se arriva un lotto molto grande, allora potrebbe essere necessario rimuovere gli eventi che i vostri clienti stanno aspettando prima di avere la possibilità di inviarli.

1

Semplice, il client deve passare il timestamp (o l'id o l'indice) dell'ultimo messaggio che hanno ricevuto.

Richiesta GET /rooms/5/messages restituisce tutti i messaggi che il server sa circa, come

[ 
    { 
    "message": "hello", 
    "timestamp": "2016-07-18T18:44:34Z" 
    }, 
    { 
    "message": "world", 
    "timestamp": "2016-07-18T18:47:16Z" 
    } 
] 

Il cliente quindi lunghe interroga il server con GET /rooms/5/messages?since=2016-07-18T18:47:16Z che restituisce sia tutti i messaggi da quel momento (se ci sono) o blocchi fino la stanza ha un nuovo messaggio.

0

I fortemente consiglia di utilizzare WebSockets. Controlla socket.io. Il polling lungo è un hack che non è necessariamente desiderabile e non è realmente "supportato".

0

Il polling lungo non è una buona idea. Nello specifico, quando si desidera monitorare dal vivo i cambiamenti che avvengono sul lato server. Esistono meccanismi in cui il server invia le notifiche ai client per le modifiche. Questo può essere ottenuto usando, come già detto in gcoreb, Socket.io (stack Nodejs) o SignalR (.net stack).

1

Inviare il numero di riferimento con tutti gli eventi. Cleint chiamerà con il numero di riferimento dell'ultimo evento ricevuto. Si bloccherà la richiesta di polling lungo se non ci sono eventi disponibili e si risponde una volta che l'evento è nuovamente disponibile con un nuovo numero di riferimento. In caso gli eventi siano già disponibili, verranno restituiti tutti gli eventi generati dopo l'evento del numero di riferimento della richiesta.

Problemi correlati