En pinlig fortælling: Hvorfor min server kun kunne håndtere 10 spillere

Hvad der kunne være endnu mere pinligt er, at jeg på et tidspunkt havde overbevist mig selv om, at 10 spillere pr. Server var normale.

Det hele startede med en idé i begyndelsen af ​​sommeren. Jeg stod på mit værelse og prøvede at tænke på et io-spil at lave (jeg besluttede, at hvis jeg skulle lave et spil, begrænsede jeg mig til at lave et io-spil for maksimalt viralt potentiale - det er en ting, jeg sværger).

Så jeg begyndte at analysere, hvad der gjorde visse io-spil (agar.io, slither.io osv.) Vanedannende. Jeg fandt sammenligninger og ligheder mellem sådanne spil, som det ses på billedet nedenfor:

Endelig landede jeg efter lidt mere brainstorming på knckout.io. Det er navnet på spillet. Prøv at blive på kortet og slå andre af. Jeg elskede det. Enkle kontroller, klart mål og en smuk spilmekaniker.

Efter at have lagt ud, hvordan jeg ønskede, at spillet skulle se ud og føle, kom jeg på arbejde. Jeg ville komme hjem fra min sommerpraktik hver dag, træne og derefter kode.

Jeg fik først spilleren til at flytte, som jeg ville. Så håndterede jeg boostingen. Så kollisionerne. Endelig var spillet færdigt og klar til at blive testet ud af offentligheden. Eller så tænkte jeg ...

Sidste weekend (for ca. en uge siden) var jeg alle sammen forstærket og klar til at vise verden, hvad jeg lavede. Så jeg tog til interwebs og fandt en lille subreddit kaldet "playmygame." Jeg skrev en kort opsummering og sendte den (ps i indlægets kommentarer, du kan tydeligt se, at jeg understregede min servers evne). Jeg ventede tålmodigt, så HUZZAH! En spiller var kommet til.

Vi gik frem og tilbage på hinanden i spillet. I mellemtiden var jeg stressende og bekymret over, hvad denne spiller tænkte. Efter at denne spiller mistede hele deres liv og blev startet fra den kamp, ​​vi var i, ventede jeg på, om de ville komme tilbage. Og det gjorde de! Men endnu bedre: spilleren satte deres navn til "ilikethisgame." Mine øjne voksede brede, og jeg fik et skyn af adrenalin! Jeg var den lykkeligste dreng i verden.

Snart sluttede andre spillere sig til, og nogle efterlod kommentarer til Reddit-indlægget. Flere spillere sagde, at de havde nydt spillet! Jeg var i ekstase. Derefter kontrollerede jeg, hvordan min server holdt op (den 15/8) ...

Det føltes som om nogen havde slået vinden ud af mig. Var dette rigtigt? Dette måtte være falsk, tænkte jeg ved mig selv. Bare to spil, og serveren har svært ved at behandle dem.

Jeg begyndte at tænke på, hvor jeg gik galt i min kode. Jeg troede helt sikkert, at kollisionsdetektering skulle være flaskehalsen. Men jeg brugte allerede firetræer til at hjælpe med at indsnævre antallet af kollisionsdetekteringskort.

Jeg var nødt til at udføre noget beskidt arbejde, så jeg spandt en ny Digital Ocean-server op til brug som min udviklingsserver. Derefter deaktiverede jeg kollisionsdetektion midlertidigt og så, at problemet stadig var der.

OK - hvis kollisionsdetektion ikke var problemet, hvad kunne det ellers være?

Jeg tænkte på, hvor meget information jeg sendte fra serveren til hver klient hvert sekund. Jeg havde denne udsendelsesfunktion, der sendte spilletilstanden ud hver 22 millisekunder til hver klient. I denne funktion filtrerede jeg unødigt den givne klients lokale spiller i en allPlayersejendom for bare at placere den lokale spiller i sin egen ejendom. Så jeg lagde ikke kun en for-løkke (filtreringen) i en anden til en løkke (udsendelsen for hver klient), men jeg tilpasser også de data, der skal sendes ud af denne udsendelsesfunktion for hver klient.

Denne tilpasning var ikke nødvendig. Jeg skulle bare være i stand til at sende status for spillet til alle uden tilpasning. Alle skal få de samme data (og dataene bør ikke skræddersys til en bestemt klient). Dette måtte være, hvor CPU'en blev spist op. Så jeg optimerede denne funktion, skubbede den op til dev-serveren og tjekkede CPU-grafen. Ingen løsning.

Med min uvidenhed begyndte jeg at overbevise mig selv om, at ~ 10-20 spillere pr. 1 kerneserver var god. Hvordan kommer jeg nu til en sådan konklusion? Min ekstreme tillid til mine tekniske evner blændede mig tydeligt fra virkeligheden. Jeg snuble på et indlæg, hvor skaberen af ​​agar.io sagde, at hans 1 kerneserver kan håndtere omkring 190 spillere. Jeg smuttede hurtigt ud af det.

Den næste synder, jeg havde stillet op, var: socket.io. Jeg brugte socket.io til at styre realtidskommunikationen mellem klienten og serveren. Jeg havde hørt før den stikkontakt. Io var ikke så let som andre alternativer.

Tilbage på dagen, hvis du ønskede at sende en besked asynkront, var du nødt til at implementere en slags hack: lang afstemning eller flashstik. Dette var fordi ikke alle webbrowsere understøttede websockets. Men de fleste browsere tilbyder nu native support. Men for at socket.io opretter en forbindelse, gør det det først ved hjælp af en af ​​de nævnte tilgængelige hacks og derefter opgraderer forbindelsen, hvis klienten understøtter en bedre måde. Selvom websockets allerede er bredt understøttet. Denne tilgang går på bekostning af CPU og hukommelse. Men ikke så meget som jeg havde troet ...

Jeg hoppede online og skrev naivt "socket io cpu problem" i Google. De første parresultater havde titlen "Node.js - Sådan debugges Node + Socket.io CPU-problemer - Serverfejl" og "Node.js - Socket.io node-server ved hjælp af høj CPU - Stack Overflow." Mine øjne lyste op. Jeg blev forsikret om, at dette var skylden i mit problem. Men jeg klikkede på den første artikel, og forfatteren nævnte, at han havde at gøre med ~ 1.500 samtidige stikforbindelser. Jeg er ingen matematikfag, men 20 spillere er betydeligt mindre end 1.500 spillere.

Bare for det skide skiftede jeg min server-side Node-app til at bruge små websockets og skiftede derefter klientsiden Node-app til at bruge native websocket-support lige inde i browseren. Jeg skubbede ændringerne op til dev-serveren og tjekkede CPU-grafen. Ingen løsning.

Min moral var på et lavt tidspunkt. Jeg begyndte at krybe sammen hver gang jeg skulle kontrollere CPU-grafen. Jeg troede, jeg ville aldrig få den blå linje til at stoppe med at løbe væk fra mig. Dette var den eneste gang, jeg nogensinde følte mig helt ude af stand til at håndtere en teknisk opgave. Men så skete det ...

Jeg sad foran CPU-grafen og vælte mig i min elendighed, da jeg bemærkede noget. Det betyder ikke noget, hvor mange fulde spil der kørte, eller hvor tæt sammen de alle blev startet. CPU'en steg konstant med en konstant hastighed. Jeg havde aldrig været længe nok til at observere dette. Hukommelsestab!

Jeg scannede min kode linje for linje og ledte efter fejlen (som jeg burde have gjort i starten). Der var det.

I mit spil er en begivenhed et objekt, der fanger information om ting som spillerdødsfald, boosts og kollisioner. Så der oprettes en begivenhed hver gang en af ​​disse ting sker.

Jeg har denne løkke, der går gennem hver begivenhed og opdaterer den. Det kaldes hver 16. ms. Når en begivenhed opfylder sin pligt, skal den slettes. Nøgleord: "formodes at."

Bingo. Jeg havde hukommelse stablet sammen samt en stigende mængde unødvendige for-loop passerer. Jeg indsatte en linje kode og voila!

Kæmpe sukk af lettelse.

Min næste opgave er at se, hvor mange spil (4 spillere pr. Spil) en server nu kan understøtte problemfrit. (Jeg kender dens mindst 12 spil, men jeg har ikke prøvet mere endnu). Nu hvor jeg ved, at antallet af begivenheder har en enorm indflydelse på CPU ... hvad vil der ske i produktionen, når alle spillere affyrer boost-, kollisions- og dødshændelser hvert sekund? Mine tests har ikke taget højde for det.

Når dette indlæg bliver viralt, og mit spil følger trop, bliver jeg også nødt til hurtigt at skalere antallet af tilgængelige servere. Jeg vil gøre det til et fremtidigt indlæg sammen med: "Hvordan knckout.io voksede til millioner af spillere." Følg mig her for opdateringer. :)