7.5 KiB
Étude serveur multijoueur temps réel
Statut
Étude non normative pour 0.2.0-0-pre.2.fix.1.
Ce document complète l'inventaire initial. Il ne choisit pas encore une stack serveur, un crate WebSocket ou une fréquence de tick unique.
Objectif
Séparer clairement :
- transport réseau ;
- protocole de session ;
- synchronisation d'état ;
- simulation authoritative ;
- services Web persistants.
Un WebSocket fournit un canal bidirectionnel ; il ne résout pas à lui seul la synchronisation multijoueur.
Plan de contrôle et plan de données
Control plane
Responsabilités plausibles :
- authentification ;
- matchmaking ;
- création/allocation de partie ;
- roster ;
- invitation/join/leave ;
- ready/start/end ;
- sélection d'une instance realtime ;
- reprise de session.
Ces opérations peuvent passer par HTTP(S), WebSocket ou une combinaison, sans être exécutées dans la boucle de simulation.
Realtime data plane
Responsabilités plausibles :
- accepter les connexions de joueurs ;
- associer connexion, joueur et session ;
- recevoir les inputs/commands ;
- sequencer les messages ;
- maintenir le tick/cycle de simulation ;
- faire évoluer l'état authoritative ;
- diffuser snapshots et deltas ;
- détecter pertes/timeouts ;
- gérer reconnexion et resynchronisation ;
- appliquer backpressure/rate limits ;
- produire observability et health.
Modèles de synchronisation
Aucun modèle unique ne convient à tous les jeux.
Input authoritative
Le client envoie principalement ses inputs.
Le serveur :
- valide l'input ;
- l'applique à la simulation ;
- avance l'état ;
- publie l'état ou son delta.
Approprié à de nombreux jeux compétitifs.
State replication
Le serveur publie :
- snapshots périodiques ;
- deltas entre snapshots ;
- revision/tick associé ;
- éventuellement ack/last-applied revision.
Le client reconstruit un état local de présentation.
Prediction / reconciliation
Pour réduire la latence perçue :
- le client prédit localement ;
- conserve les inputs non confirmés ;
- reçoit l'état serveur ;
- corrige/rejoue si nécessaire.
À réserver aux jeux qui en ont besoin.
Rollback
Particulièrement pertinent pour certains jeux de combat :
- historique court d'états ;
- inputs retardés ou prédits ;
- rollback/re-simulation.
Ce modèle ne doit pas contaminer le runtime de tous les jeux.
Contrats techniques candidats
Envelope réseau
Champs conceptuels possibles :
- protocol version ;
- message type ;
- session id ;
- player id/connection id si nécessaire ;
- sequence ;
- server tick ;
- client tick/time ;
- payload.
Le format exact n'est pas encore décidé.
Snapshot
Doit permettre :
- état complet cohérent ;
- revision/tick ;
- application atomique côté client ;
- point de reprise après resync.
Delta
Doit préciser :
- base revision ;
- target revision ;
- mutations ;
- comportement si la base manque.
Un delta manquant doit conduire à une resynchronisation contrôlée, pas à une divergence silencieuse.
Reconnexion et resynchronisation
Cas à traiter :
- coupure courte ;
- suspension mobile ;
- changement de réseau ;
- client trop en retard ;
- trou dans les séquences ;
- restart d'une instance serveur.
États conceptuels possibles :
Disconnected
Connecting
Joining
Synchronized
Resynchronizing
Leaving
Le jeu ne doit pas confondre « socket ouvert » et « état de gameplay synchronisé ».
Rooms, instances et scaling
Pour plusieurs parties simultanées :
- une room/session possède une autorité unique à un instant donné ;
- les connexions sont routées vers l'instance responsable ;
- l'instance peut héberger plusieurs rooms selon charge ;
- la distribution des rooms peut évoluer indépendamment du protocole client ;
- les données persistantes ne doivent pas être écrites dans la DB à chaque tick sans nécessité.
À plus grande échelle, il faudra étudier :
- session placement ;
- shard/region ;
- sticky routing ;
- handoff/migration ;
- recovery après crash ;
- autoscaling ;
- limites par instance.
Interest management
Pour un petit Snake 2 joueurs, diffuser tout l'état peut être acceptable.
Pour une map plus grande/MMORPG, il faut pouvoir limiter les données à :
- zone visible ;
- proximité ;
- équipe ;
- objets pertinents ;
- fréquence adaptée au type d'entité.
L'interest management appartient au service realtime/game server, pas au renderer client.
Persistence
Séparer :
État éphémère
- positions ;
- velocities ;
- animation/state machine ;
- projectiles ;
- tick courant.
État durable
- compte ;
- progression ;
- inventory ;
- résultat de match ;
- rewards ;
- classement.
Le durable est persisté à des frontières métier appropriées, pas mécaniquement à chaque frame.
Sécurité / anti-cheat
Principes candidats :
- ne pas faire confiance à une position envoyée directement par un client compétitif ;
- valider les actions et contraintes de jeu côté serveur ;
- rate limit ;
- protéger join/session tokens ;
- empêcher replay/double-submit d'actions sensibles ;
- enregistrer suffisamment de données pour diagnostiquer une divergence ou fraude.
Observability
Le realtime nécessite au minimum des dimensions dédiées :
- connexions actives ;
- rooms actives ;
- joueurs/session ;
- tick duration ;
- tick lag ;
- queue/backpressure ;
- messages/s ;
- bytes/s ;
- reconnects ;
- resyncs ;
- dropped/invalid inputs ;
- snapshot/delta sizes ;
- errors par protocole/version.
Le logging par domaines devra pouvoir distinguer transport, session, sync et simulation.
Technologies
Le choix exact reste volontairement ouvert.
Candidats à étudier ultérieurement selon le POC serveur :
- HTTP(S) pour control plane/API ;
- WebSocket pour data plane bidirectionnel ;
- gRPC pour backend-to-backend ou services structurés ;
- WebRTC uniquement si un besoin P2P/media le justifie.
Le framework ne doit pas imposer une technologie unique à tous les services.
Pressure test rapide
Snake 2 joueurs
Peut probablement fonctionner avec :
- tick modéré ;
- inputs directionnels ;
- état authoritative ;
- snapshot/delta simple ;
- interpolation limitée ;
- reconnect/resync.
Racing
Exigera potentiellement :
- tick plus fréquent ;
- prediction/reconciliation ;
- interpolation ;
- lag compensation selon gameplay ;
- snapshots/deltas optimisés.
Fighting 1v1
Peut nécessiter :
- input synchronization très stricte ;
- rollback netcode ou stratégie équivalente ;
- historique court déterministe.
MMORPG
Exigera potentiellement :
- zones/shards ;
- interest management ;
- sessions longues ;
- persistence structurée ;
- chat/presence ;
- recovery/scaling.
Questions ouvertes pour le futur POC serveur
- Axum + Tokio + WebSocket suffit-il pour le premier service realtime ?
- Une room est-elle une task, un actor, un shard ou une structure pilotée par scheduler ?
- Quelle cadence de tick pour chaque genre ?
- Quel codec : JSON de debug, bincode/postcard/protobuf/autre en production ?
- Quelle frontière entre types de protocole partagés et logique serveur ?
- Comment versionner le protocole sans coupler toutes les apps ?
- Comment tester déterminisme, perte de paquets logique, reconnexion et resync ?
- Quand introduire Redis/NATS/Kafka ou autre coordination, si jamais nécessaire ?
Ces choix appartiennent à la future planification/POC, pas à cette étude de réservation.