Condizioni di gara nella sincronizzazione del client

2

Ho un'app web il cui server crea un client per ogni connessione web socket. Un client funge da intermediario tra la connessione web socket e una singola istanza di un hub. L'Hub mantiene una serie di client registrati e trasmette messaggi ai client. Funziona piuttosto bene, ma il problema è che un client potrebbe perdere gli eventi tra quando il server genera il pacchetto di stato iniziale che il client riceve sulla connessione e quando il client è registrato con l'hub e inizia a ricevere gli eventi di trasmissione.

La mia idea è di registrare il client con l'hub prima che qualsiasi informazione venga recuperata dal db. Ciò garantirebbe che il client non perdesse nessuna trasmissione, anche se ora potrebbe ricevere messaggi che sono già applicati allo stato iniziale che riceve. Per consentire al client di ignorare questi messaggi, potrei includere un timestamp monotonico sia nel pacchetto di stato iniziale che negli eventi di trasmissione.

Riesci a pensare ad una soluzione più elegante / più semplice?

    
posta elmango 08.08.2018 - 23:43
fonte

1 risposta

1

Hai un sistema distribuito con più flussi di dati simultanei. Quelli sono complicati, ma non irrisolvibili. A causa di questa natura distribuita, non è possibile affermare una relazione prima / dopo tra le origini dati (DB e coda messaggi). Mentre una consegna esatta una sola volta potrebbe non essere possibile, almeno una volta la consegna è di solito.

La tua idea di utilizzare un timestamp monotono è molto buona, tranne che una fonte di tempo monotona a livello mondiale potrebbe non esistere. È possibile generalizzare questi timestamp al concetto di un ID messaggio , che potrebbe essere già richiesto dalla coda dei messaggi sotto il cofano (ad esempio se utilizza il protocollo AMQP). Un ID messaggio deve essere univoco ma non necessariamente monotonico, quindi è possibile ad es. usa gli UUID per generarli.

Quindi, assumendo un database ACID, i messaggi vengono scritti nel database prima sono resi disponibili nella coda dei messaggi e i messaggi in coda vengono consegnati in ordine:

  • Il client si connette alla coda dei messaggi. A seconda della coda, la coda ora salverà tutti i messaggi in sospeso, oppure dovremo consumare qualsiasi messaggio in arrivo e memorizzarli in un buffer.

  • Nel frattempo, caricare lo stato corrente dal DB. Questo stato dovrebbe includere gli ultimi messaggi. Possiamo elaborare questi messaggi e creare un set dei loro ID.

  • Durante il consumo dei messaggi dalla coda dei messaggi, elimina il messaggio se il suo ID è già stato visto nello stato dal database.

  • Una volta che il primo messaggio è stato visto, le informazioni sullo stato possono essere scartate: tutti i messaggi futuri saranno freschi.

In questa progettazione, il database è la fonte della verità e la coda dei messaggi è solo un'ottimizzazione delle prestazioni per la gestione di più utenti. Vale la pena leggere con attenzione la documentazione della coda dei messaggi, poiché potrebbe offrire funzionalità come la persistenza di per sé.

A seconda del dominio del problema, potresti ottenere una maggiore flessibilità. Per esempio. se si dispone di un'applicazione di chat come Slack, il client non ha bisogno di ricevere i messaggi in ordine purché vengano visualizzati in ordine (in questo caso, un'indicazione temporale fornita dal server è sufficiente per l'ordine). E il server non deve spingere la cronologia della chat attraverso la connessione websocket, poiché il client può richiedere la cronologia necessaria.

    
risposta data 09.08.2018 - 08:25
fonte

Leggi altre domande sui tag