Megapack: Πώς το Factorio έλυσε το πρόβλημα με πολλούς παίκτες 200 παικτών

Megapack: Πώς το Factorio έλυσε το πρόβλημα με πολλούς παίκτες 200 παικτών
Τον Μάιο του τρέχοντος έτους συμμετείχα ως παίκτης στο Εκδηλώσεις KatherineOfSky MMO. Παρατήρησα ότι όταν ο αριθμός των παικτών φτάνει σε έναν συγκεκριμένο αριθμό, κάθε λίγα λεπτά κάποιοι από αυτούς «πέφτουν». Ευτυχώς για εσάς (αλλά όχι για μένα), ήμουν ένας από αυτούς τους παίκτες κάθε φοράακόμα και με καλή σύνδεση. Το πήρα ως προσωπική πρόκληση και άρχισα να αναζητώ τις αιτίες του προβλήματος. Μετά από τρεις εβδομάδες εντοπισμού σφαλμάτων, δοκιμών και επιδιόρθωσης, το σφάλμα διορθώθηκε τελικά, αλλά το ταξίδι δεν ήταν τόσο εύκολο.

Τα προβλήματα σε παιχνίδια για πολλούς παίκτες είναι πολύ δύσκολο να εντοπιστούν. Εμφανίζονται συνήθως κάτω από πολύ συγκεκριμένες παραμέτρους δικτύου και κάτω από πολύ συγκεκριμένες καταστάσεις παιχνιδιού (σε αυτήν την περίπτωση, πάνω από 200 παίκτες). Και ακόμη και όταν ένα πρόβλημα μπορεί να αναπαραχθεί, δεν μπορεί να διορθωθεί σωστά, επειδή η εισαγωγή σημείων διακοπής σταματά το παιχνίδι, χαλάει τα χρονόμετρα και συνήθως προκαλεί το χρονικό όριο της σύνδεσης να λήξει λόγω χρονικού ορίου. Αλλά χάρη στην επιμονή και ένα υπέροχο εργαλείο που ονομάζεται αδέξιος Κατάφερα να καταλάβω τι συμβαίνει.

Εν ολίγοις, λόγω ενός σφάλματος και ατελούς υλοποίησης της προσομοίωσης κατάστασης καθυστέρησης, ο πελάτης βρισκόταν μερικές φορές σε μια κατάσταση όπου έπρεπε να στείλει ένα πακέτο δικτύου σε έναν κύκλο ρολογιού, που αποτελείται από ενέργειες εισαγωγής παίκτη για την επιλογή περίπου 400 οντοτήτων παιχνιδιού ( το ονομάζουμε «μεγαπακέτο»). Μετά από αυτό, ο διακομιστής όχι μόνο χρειάζεται να λάβει σωστά όλες αυτές τις ενέργειες εισαγωγής, αλλά και να τις στείλει σε όλους τους άλλους πελάτες. Εάν έχετε 200 πελάτες, αυτό γίνεται γρήγορα πρόβλημα. Το κανάλι προς τον διακομιστή γίνεται γρήγορα φραγμένο, με αποτέλεσμα να χαθούν πακέτα και ένας καταρράκτης πακέτων που ζητήθηκαν εκ νέου. Η αναβολή ενεργειών εισαγωγής αναγκάζει περισσότερους πελάτες να αρχίσουν να στέλνουν megapackets και η χιονοστιβάδα τους γίνεται ακόμα πιο δυνατή. Οι επιτυχημένοι πελάτες καταφέρνουν να ανακάμψουν, όλοι οι υπόλοιποι πέφτουν.

Megapack: Πώς το Factorio έλυσε το πρόβλημα με πολλούς παίκτες 200 παικτών
Το πρόβλημα ήταν αρκετά θεμελιώδες και μου πήρε 2 εβδομάδες για να το διορθώσω. Είναι αρκετά τεχνικό, οπότε θα εξηγήσω τις ζουμερές τεχνικές λεπτομέρειες παρακάτω. Αλλά πρώτα, πρέπει να γνωρίζετε ότι από την έκδοση 0.17.54, που κυκλοφόρησε στις 4 Ιουνίου, ενόψει των προσωρινών προβλημάτων σύνδεσης, το multiplayer έχει γίνει πιο σταθερό και η καθυστέρηση απόκρυψης είναι πολύ λιγότερο λάθη (λιγότερο φρενάρισμα και τηλεμεταφορά). Επίσης, έχω αλλάξει τον τρόπο με τον οποίο κρύβονται οι καθυστερήσεις μάχης και ελπίζω ότι αυτό θα τις κάνει λίγο πιο ομαλές.

Multiplayer Mega Pack - Τεχνικές λεπτομέρειες

Για να το θέσουμε απλά, η λειτουργία πολλών παικτών σε ένα παιχνίδι λειτουργεί ως εξής: όλοι οι πελάτες προσομοιώνουν την κατάσταση του παιχνιδιού λαμβάνοντας και στέλνοντας μόνο στοιχεία εισόδου παίκτη (ονομάζονται "ενέργειες εισόδου" Ενέργειες εισαγωγής). Το κύριο καθήκον του διακομιστή είναι η μεταφορά Ενέργειες εισαγωγής και διασφαλίζοντας ότι όλοι οι πελάτες εκτελούν τις ίδιες ενέργειες στον ίδιο κύκλο. Μπορείτε να διαβάσετε περισσότερα για αυτό στην ανάρτηση. FFF-149.

Εφόσον ο διακομιστής πρέπει να λάβει αποφάσεις σχετικά με τις ενέργειες που θα κάνει, οι ενέργειες του παίκτη κινούνται κατά την ακόλουθη διαδρομή: δράση παίκτη -> πελάτης παιχνιδιού -> δίκτυο -> διακομιστής -> δίκτυο -> πελάτης παιχνιδιού. Αυτό σημαίνει ότι κάθε ενέργεια του παίκτη εκτελείται μόνο αφού έχει κάνει μια διαδρομή μετ' επιστροφής μέσω του δικτύου. Εξαιτίας αυτού, το παιχνίδι θα φαινόταν τρομερά αργό, οπότε σχεδόν αμέσως μετά την εμφάνιση του multiplayer στο παιχνίδι, εισήχθη ένας μηχανισμός απόκρυψης καθυστερήσεων. Η απόκρυψη καθυστέρησης προσομοιώνει την είσοδο του παίκτη χωρίς να λαμβάνει υπόψη τις ενέργειες άλλων παικτών και τη λήψη αποφάσεων διακομιστή.

Megapack: Πώς το Factorio έλυσε το πρόβλημα με πολλούς παίκτες 200 παικτών
Το Factorio έχει κατάσταση παιχνιδιού κατάσταση παιχνιδιού είναι η πλήρης κατάσταση του χάρτη, του προγράμματος αναπαραγωγής, των οντοτήτων και οτιδήποτε άλλο. Προσομοιώνεται ντετερμινιστικά σε όλους τους πελάτες με βάση τις ενέργειες που λαμβάνονται από τον διακομιστή. Η κατάσταση του παιχνιδιού είναι ιερή και αν αρχίσει να διαφέρει από τον διακομιστή ή οποιονδήποτε άλλο πελάτη, τότε πραγματοποιείται αποσυγχρονισμός.

Αλλά κατάσταση παιχνιδιού έχουμε μια κατάσταση καθυστερήσεων Κατάσταση λανθάνουσας κατάστασης. Περιέχει ένα μικρό υποσύνολο της κύριας κατάστασης. Κατάσταση λανθάνουσας κατάστασης δεν είναι ιερό και απλώς αντιπροσωπεύει μια εικόνα του πώς θα είναι η κατάσταση του παιχνιδιού στο μέλλον με βάση τις εισροές από τον παίκτη Ενέργειες εισαγωγής.

Για να γίνει αυτό, κρατάμε ένα αντίγραφο του δημιουργημένου Ενέργειες εισαγωγής στην ουρά καθυστέρησης.

Megapack: Πώς το Factorio έλυσε το πρόβλημα με πολλούς παίκτες 200 παικτών
Δηλαδή, στο τέλος της διαδικασίας στην πλευρά του πελάτη, η εικόνα μοιάζει κάπως έτσι:

  1. Ισχύουν Ενέργειες εισαγωγής όλοι οι παίκτες να κατάσταση παιχνιδιού τον τρόπο λήψης αυτών των ενεργειών εισαγωγής από τον διακομιστή.
  2. Αφαιρέστε τα πάντα από την ουρά καθυστέρησης Ενέργειες εισαγωγής, στα οποία, σύμφωνα με τον διακομιστή, έχουν ήδη εφαρμοστεί κατάσταση παιχνιδιού.
  3. Διαγράφω Κατάσταση λανθάνουσας κατάστασης και να το επαναφέρετε ώστε να φαίνεται ακριβώς το ίδιο με κατάσταση παιχνιδιού.
  4. Εφαρμόστε όλες τις ενέργειες από την ουρά καθυστέρησης έως Κατάσταση λανθάνουσας κατάστασης.
  5. Με βάση δεδομένα κατάσταση παιχνιδιού и Κατάσταση λανθάνουσας κατάστασης αποδώσει το παιχνίδι στον παίκτη.

Όλα αυτά επαναλαμβάνονται σε κάθε χτύπημα.

Πολύ δύσκολο? Μην χαλαρώνετε, δεν είναι μόνο αυτό. Για να αντισταθμίσουμε τις αναξιόπιστες συνδέσεις στο Διαδίκτυο, δημιουργήσαμε δύο μηχανισμούς:

  • Παράλειψη τικ: όταν το αποφασίσει ο διακομιστής Ενέργειες εισαγωγής θα εκτελεστεί στο τακτ του παιχνιδιού, τότε αν δεν έχει λάβει Ενέργειες εισαγωγής κάποιος παίκτης (για παράδειγμα, λόγω αυξημένης καθυστέρησης), δεν θα περιμένει, αλλά θα ενημερώσει αυτόν τον πελάτη «Δεν έλαβα υπόψη σας Ενέργειες εισαγωγής, θα προσπαθήσω να τα προσθέσω στην επόμενη γραμμή. Αυτό γίνεται έτσι ώστε λόγω προβλημάτων με τη σύνδεση (ή με τον υπολογιστή) ενός παίκτη, η ενημέρωση χάρτη να μην επιβραδύνεται για όλους τους άλλους. Αξίζει να σημειωθεί ότι Ενέργειες εισαγωγής δεν αγνοούνται, αλλά απλώς αναβάλλονται.
  • Πλήρης καθυστέρηση μετ' επιστροφής: Ο διακομιστής προσπαθεί να μαντέψει ποια είναι η καθυστέρηση μετ' επιστροφής μεταξύ πελάτη και διακομιστή για κάθε πελάτη. Κάθε 5 δευτερόλεπτα, διαπραγματεύεται μια νέα καθυστέρηση με τον πελάτη όπως απαιτείται (ανάλογα με τον τρόπο συμπεριφοράς της σύνδεσης στο παρελθόν) και αυξάνει ή μειώνει την καθυστέρηση μετ' επιστροφής ανάλογα.

Από μόνοι τους, αυτοί οι μηχανισμοί είναι αρκετά απλοί, αλλά όταν χρησιμοποιούνται μαζί (κάτι που συμβαίνει συχνά με προβλήματα σύνδεσης), η λογική του κώδικα γίνεται δύσκολη στη διαχείριση και με πολλές περιπτώσεις ακμών. Επιπλέον, όταν αυτοί οι μηχανισμοί μπαίνουν στο παιχνίδι, ο διακομιστής και η ουρά καθυστέρησης πρέπει να εφαρμόσουν σωστά μια ειδική Δράση εισαγωγής καλείται StopMovementInTheNextTick. Χάρη σε αυτό, σε περίπτωση προβλημάτων σύνδεσης, ο χαρακτήρας δεν θα τρέξει μόνος του (για παράδειγμα, κάτω από ένα τρένο).

Τώρα πρέπει να σας εξηγήσω πώς λειτουργεί η επιλογή οντοτήτων. Ένας από τους περασμένους τύπους Δράση εισαγωγής είναι μια αλλαγή στην κατάσταση επιλογής μιας οντότητας. Ενημερώνει σε όλους ποια οντότητα τοποθέτησε το πρόγραμμα αναπαραγωγής με το ποντίκι. Όπως μπορείτε να δείτε, αυτή είναι μια από τις πιο συχνές ενέργειες εισαγωγής που στέλνουν οι πελάτες, επομένως για να εξοικονομήσουμε εύρος ζώνης, το έχουμε βελτιστοποιήσει ώστε να καταλαμβάνει όσο το δυνατόν λιγότερο χώρο. Αυτό υλοποιείται ως εξής: όταν επιλέγεται κάθε οντότητα, αντί να αποθηκεύει απόλυτες συντεταγμένες χάρτη υψηλής ακρίβειας, το παιχνίδι αποθηκεύει μια σχετική μετατόπιση χαμηλής ακρίβειας από την προηγούμενη επιλογή. Αυτό λειτουργεί καλά επειδή η επιλογή του ποντικιού συνήθως συμβαίνει πολύ κοντά στην προηγούμενη επιλογή. Αυτό δημιουργεί δύο σημαντικές απαιτήσεις: Ενέργειες εισαγωγής δεν πρέπει ποτέ να παραλείπονται και πρέπει να γίνονται με τη σωστή σειρά. Αυτές οι απαιτήσεις πληρούνται για κατάσταση παιχνιδιού. Αλλά από το καθήκον λανθάνουσα κατάσταση στο "looking αρκετά καλό" για τον παίκτη, δεν είναι ικανοποιημένοι στην κατάσταση καθυστέρησης. Κατάσταση λανθάνουσας κατάστασης δεν λαμβάνει υπόψη πολλές οριακές περιπτώσειςσχετίζεται με παράβλεψη ρολογιών και αλλαγή των καθυστερήσεων μετάδοσης μετ' επιστροφής.

Μπορείτε ήδη να μαντέψετε πού πηγαίνει αυτό. Τέλος, αρχίζουμε να βλέπουμε τις αιτίες του προβλήματος των megapackage. Η ρίζα του προβλήματος είναι ότι η λογική επιλογής οντοτήτων βασίζεται Κατάσταση λανθάνουσας κατάστασης, και αυτή η κατάσταση δεν περιέχει πάντα τις σωστές πληροφορίες. Έτσι το megapacket δημιουργείται ως εξής:

  1. Η συσκευή αναπαραγωγής αντιμετωπίζει προβλήματα σύνδεσης.
  2. Οι μηχανισμοί παράβλεψης κύκλων και ρύθμισης της καθυστέρησης μετάδοσης μετ' επιστροφής μπαίνουν στο παιχνίδι.
  3. Η ουρά κατάστασης καθυστέρησης δεν λαμβάνει υπόψη αυτούς τους μηχανισμούς. Αυτό προκαλεί την πρόωρη κατάργηση ορισμένων ενεργειών ή την εκτέλεση με λανθασμένη σειρά, με αποτέλεσμα λανθασμένη Κατάσταση λανθάνουσας κατάστασης.
  4. Η συσκευή αναπαραγωγής δεν έχει πρόβλημα σύνδεσης και προσομοιώνει έως και 400 κύκλους για να καλύψει τη διαφορά με τον διακομιστή.
  5. Σε κάθε κύκλο, μια νέα ενέργεια δημιουργείται και προετοιμάζεται για αποστολή στον διακομιστή, αλλάζοντας την επιλογή οντότητας.
  6. Ο πελάτης στέλνει ένα megapacket 400+ αλλαγών επιλογής οντοτήτων στον διακομιστή (και με άλλες ενέργειες: κατάσταση πυροδότησης, κατάσταση βάδισης κ.λπ. επίσης υπέστη αυτό το πρόβλημα).
  7. Ο διακομιστής λαμβάνει 400 ενέργειες εισαγωγής. Δεδομένου ότι δεν επιτρέπεται η παράλειψη μιας μεμονωμένης ενέργειας εισόδου, δίνει οδηγίες σε όλους τους πελάτες να εκτελέσουν αυτές τις ενέργειες και τις στέλνει μέσω του δικτύου.

Η ειρωνεία είναι ότι ένας μηχανισμός σχεδιασμένος για τη διατήρηση του εύρους ζώνης οδήγησε σε τεράστια πακέτα δικτύου.

Επιλύσαμε αυτό το ζήτημα επιδιορθώνοντας όλες τις περιπτώσεις άκρων ενημέρωσης και υποστήριξη ουράς καθυστέρησης. Παρόλο που χρειάστηκε αρκετός χρόνος, άξιζε να το κάνετε σωστά στο τέλος αντί να βασίζεστε σε γρήγορες εισβολές.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο