Ik ben bezig met een applicatie die door een aantal clients tegelijk gebruikt zal worden, en ik wil graag alle clients in (min of meer) real-time met elkaar synchronizeren. Denk bijvoorbeeld aan Google Docs waar je met meerdere mensen tegelijk kunt werken aan een excel sheet oid (maar dan iets eenvoudiger). Ik heb echter twee ideeën om de synchronizatie te doen maar kan niet kiezen welke nou beter is.
Laat ik beginnen met een heel erg uitgeklede versie van wat ik wil bereiken, hopelijk is dat genoeg als uitleg, zo niet dan kan ik meer details geven. Ik werk in .NET (C#) en wil graag SignalR gebruiken voor de communicatie, maar voor deze vraag is dat eigenlijk niet zo van belang.
De applicatie heeft een lijst met data. Deze lijst met data moet gesynchronizeerd worden naar alle andere clients. Elke client kan items toevoegen aan de lijst, of bestaande items bewerken, of zelfs verwijderen. Zodra een item toegevoegd, bewerkt of verwijderd wordt moet dat ook in real time (nou ja, toch wel binnen een seconde) bij alle andere clients automatisch updaten.
Naast alle clients moet er natuurlijk ook een server zijn die de communicatie tussen de clients regelt. Tenminste, dat lijkt me de meest logische oplossing. Clients praten niet met elkaar, maar praten altijd met de server, en de server kan dan weer met alle andere clients praten.
Momenteel is de opzet van de client/server communicatie als volgt:
De voordelen van deze opzet leken mij:
Het alternatief dat ik kan bedenken is om de updates vanuit de server naar de client ook als 'incremental' te doen. Oftewel: een client stuurt een nieuw item, en de server stuurt alleen dat nieuwe item door aan alle andere clients. Dit houdt de communicatie altijd kort, zelfs als de lijst enorm lang is (omdat alleen de updates aan de lijst doorgestuurd worden).
Hier zie ik echter een groot nadeel: clients kunnen 'out of sync' gaan lopen als ze een update missen bijvoorbeeld. Die update komt dan nooit meer aan en omdat ze nooit de hele state ontvangen komt dat ook nooit meer goed. Er zal dus op een of andere manier af en toe gechecked moeten worden of de clients nog in sync zijn (bijvoorbeeld een hash van de state rondsturen en kijken of die nog hetzelfde is). Maar als dan blijkt dat een client niet meer in sync loopt zal toch echt de hele state opgestuurd moeten worden, en ben ik weer terug bij het probleem in mijn eerste idee. Ook als een client later binnenkomt zal hij de state moeten ontvangen.
Dit lijkt me echter minder erg dan elke keer de gehele state opsturen. Een client die laat binnenkomt kan best even een wachtscherm krijgen terwijl de gehele state opgehaald wordt, en in het extreme geval dat iemand niet meer in sync loopt is dat ook niet zo'n punt. Het tweede idee lijkt me dus uiteindelijk beter. Echter volgens mij is dit ook veel ingewikkelder te programmeren...
Echter vraag ik me af hoe dit "normaal" in zijn werk gaat. Dit probleem lijkt me al lang en breed opgelost, want volgens mij moet elke online game (om maar iets te noemen) hier ook mee om gaan. Ik wil voorkomen dat ik het wiel opnieuw ga uitvinden, echter kan ik maar heel weinig informatie vinden over dit soort onderwerpen. Alles wat ik kan vinden gaat meteen veel te diep door in dingen als lag compensatie etc. Daar ben ik niet zo in geinteresseerd. Ik vind het prima als een client een delay van 1 seconde heeft oid.
Long story short: ik kan niet kiezen uit twee methodes om clients te synchronizeren:
1. Clients sturen incremental updates, server stuurt de gehele nieuwe state door aan alle clients.
2. Clients sturen incremental updates, server stuurt incremental updates naar alle clients. Verder geen synchronizatie tussen clients (en dus moet ik gaan checken of de state nog wel in sync is).
Heeft iemand input?
Laat ik beginnen met een heel erg uitgeklede versie van wat ik wil bereiken, hopelijk is dat genoeg als uitleg, zo niet dan kan ik meer details geven. Ik werk in .NET (C#) en wil graag SignalR gebruiken voor de communicatie, maar voor deze vraag is dat eigenlijk niet zo van belang.
De applicatie heeft een lijst met data. Deze lijst met data moet gesynchronizeerd worden naar alle andere clients. Elke client kan items toevoegen aan de lijst, of bestaande items bewerken, of zelfs verwijderen. Zodra een item toegevoegd, bewerkt of verwijderd wordt moet dat ook in real time (nou ja, toch wel binnen een seconde) bij alle andere clients automatisch updaten.
Naast alle clients moet er natuurlijk ook een server zijn die de communicatie tussen de clients regelt. Tenminste, dat lijkt me de meest logische oplossing. Clients praten niet met elkaar, maar praten altijd met de server, en de server kan dan weer met alle andere clients praten.
Momenteel is de opzet van de client/server communicatie als volgt:
- De server heeft als enige de definitieve lijst met data welke altijd correct geacht wordt. Dit noem ik de 'State' van de applicatie. In het echt zit er veel meer in dan alleen deze lijst met data maar voor nu is dit een ok voorbeeld.
- Clients sturen incremental updates van de data naar de server. Bijvoorbeeld: een nieuw item in de lijst, of een bewerkt item, of een id om te verwijderen.
- De server update dan zijn eigen State (voegt het item toe, bewerkt het item, etc).
- De server stuurt dan naar alle clients de nieuwe State.
- Clients ontvangen de state en updaten hun applicatie (de lijst met data) om de nieuwe data te tonen.
De voordelen van deze opzet leken mij:
- Clients kunnen binnenvallen wanneer ze willen en krijgen meteen de gehele State, zijn dus meteen up-to-date.
- Berichten van Client naar Server mogen gemist worden (connectie problemen ofzo). De server State wordt dan niet geupdate (update gaat verloren) en de andere clients krijgen de update niet door, maar zodra er een nieuwe update komt krijgen alle clients weer dezelfde State en lopen ze niet 'van elkaar weg'.
- In andere woorden, de clients zijn altijd (lees: na elke state update) compleet in sync en lopen nooit uit sync omdat ze altijd de gehele state krijgen. Hoogstens gaat er een update verloren maar dat is niet zo erg.
Het alternatief dat ik kan bedenken is om de updates vanuit de server naar de client ook als 'incremental' te doen. Oftewel: een client stuurt een nieuw item, en de server stuurt alleen dat nieuwe item door aan alle andere clients. Dit houdt de communicatie altijd kort, zelfs als de lijst enorm lang is (omdat alleen de updates aan de lijst doorgestuurd worden).
Hier zie ik echter een groot nadeel: clients kunnen 'out of sync' gaan lopen als ze een update missen bijvoorbeeld. Die update komt dan nooit meer aan en omdat ze nooit de hele state ontvangen komt dat ook nooit meer goed. Er zal dus op een of andere manier af en toe gechecked moeten worden of de clients nog in sync zijn (bijvoorbeeld een hash van de state rondsturen en kijken of die nog hetzelfde is). Maar als dan blijkt dat een client niet meer in sync loopt zal toch echt de hele state opgestuurd moeten worden, en ben ik weer terug bij het probleem in mijn eerste idee. Ook als een client later binnenkomt zal hij de state moeten ontvangen.
Dit lijkt me echter minder erg dan elke keer de gehele state opsturen. Een client die laat binnenkomt kan best even een wachtscherm krijgen terwijl de gehele state opgehaald wordt, en in het extreme geval dat iemand niet meer in sync loopt is dat ook niet zo'n punt. Het tweede idee lijkt me dus uiteindelijk beter. Echter volgens mij is dit ook veel ingewikkelder te programmeren...
Echter vraag ik me af hoe dit "normaal" in zijn werk gaat. Dit probleem lijkt me al lang en breed opgelost, want volgens mij moet elke online game (om maar iets te noemen) hier ook mee om gaan. Ik wil voorkomen dat ik het wiel opnieuw ga uitvinden, echter kan ik maar heel weinig informatie vinden over dit soort onderwerpen. Alles wat ik kan vinden gaat meteen veel te diep door in dingen als lag compensatie etc. Daar ben ik niet zo in geinteresseerd. Ik vind het prima als een client een delay van 1 seconde heeft oid.
Long story short: ik kan niet kiezen uit twee methodes om clients te synchronizeren:
1. Clients sturen incremental updates, server stuurt de gehele nieuwe state door aan alle clients.
2. Clients sturen incremental updates, server stuurt incremental updates naar alle clients. Verder geen synchronizatie tussen clients (en dus moet ik gaan checken of de state nog wel in sync is).
Heeft iemand input?