Progettazione di un meccanismo per sincronizzare gli stati con i comandi, nonostante le incoerenze temporali / di rete

1

Ho due client browser: A e B . Comunicano attraverso un server di segnalazione Server .

A ha un heartbeat clientide che segnala il ClientState ad altri client. ClientState può essere uno dei seguenti:

  • StateFoo
  • StateBar

A volte, B vuole cambiare lo stato di A . Mantiene una rappresentazione di A localmente. Quando viene visualizzato "Cambia% da% in A ", modifica StateBar (rappresentazione locale di uno stato del dispositivo remoto) prima localmente (a scopi UX), quindi segnala A.ClientState per modificare Server su ClientState : lo stato locale.

Questo di solito funziona, ma occasionalmente ci sono problemi di temporizzazione in cui l'heartbeat da A ripristinerà la modifica dello stato manuale che A ha avviato perché un heartbeat è stato inviato "a volte intorno" quando B ha inviato il segnale di cambiamento di stato.

Sto pensando a due approcci per risolvere questo problema:

  1. Timing: controlla se il server sta inviando qualcosa che è stato attivato dopo che ho modificato lo stato localmente. Questo tipo di funziona, ma se B invia un heartbeat subito dopo aver avviato una modifica dello stato da B , questo non funzionerà.
  2. Prioritizzazione dei comandi: se l'ultima cosa che ha modificato lo stato era un comando, attendere n secondi prima di consentire un heartbeat (non un comando) per aggiornare nuovamente lo stato.

Non mi piace A perché riguarda un numero magico. I problemi di connettività di rete potrebbero spingere un ritardo oltre il 2 secondi.

Quali tipi di schemi sono disponibili per risolvere questo problema? La lingua non ha molta importanza; anche se sto usando C # / JS / SignalR nel caso abbia importanza.

    
posta SB2055 19.06.2017 - 14:50
fonte

1 risposta

1

Mantieni un numero di versione su ClientState. Incrementalo ogni volta che lo stato cambia.

Quando il client B invia una modifica al client A, B conserva la registrazione della versione successiva che si aspetta da A. Quando riceve un heartbeat da A che ha una versione più piccola, può ignorare lo stato in tale heartbeat.

Il modo più sicuro per aggirare questo problema è esaminare la prima legge del design di oggetti distribuiti: don ' distribuire. Invece, rendere il server di segnalazione la fonte della verità per tutti i clienti piuttosto che ogni client che è la sua fonte di verità. Altrimenti, stai affrontando il problema dei generali bizantini . E questo è difficile da risolvere. Anche il suggerimento di cui sopra non copre il caso in cui A e B decidono di cambiare lo stato di A allo stesso tempo.

    
risposta data 21.06.2017 - 16:30
fonte