Apkaunojoša pasaka: kāpēc mans serveris varēja apstrādāt tikai 10 spēlētājus?

Vēl nepatīkamāk varētu būt tas, ka vienā brīdī es biju pārliecinājies, ka 10 spēlētāji uz serveri ir normāli.

Viss sākās ar ideju vasaras sākumā. Es stāvēju savā istabā un mēģināju iedomāties, kādu io spēli izveidot (es izlēmu, vai es taisīšu spēli, es ierobežoju sevi, lai izveidotu io spēli, lai iegūtu maksimālu vīrusu potenciālu - es zvēru, ka tā ir lieta).

Es sāku analizēt to, kas dažām io spēlēm (agar.io, slither.io utt.) Radīja atkarību. Es atradu šādu spēļu salīdzinājumus un līdzības, kā redzams zemāk esošajā attēlā:

Visbeidzot, pēc nedaudz vairāk ideju vētras, es nokļuvu vietnē knckout.io. Tas ir spēles nosaukums. Centieties palikt kartē un notriekt citus. Man tas patika. Vienkārša vadība, skaidrs mērķis un skaists spēļu mehāniķis.

Izklāstījis, kā es gribēju, lai spēle izskatās un jūtas, es ķēros pie darba. Es katru dienu atgrieztos mājās no vasaras prakses, trenējos, pēc tam kodēju.

Vispirms es panācu, lai spēlētājs kustētos, kā es gribēju. Tad es rīkojos ar palielināšanu. Tad sadursmes. Visbeidzot, spēle bija pabeigta un gatava to pārbaudīt sabiedrībai. Vai nu es domāju ...

Pagājušajā nedēļas nogalē (apmēram pirms nedēļas) es visi biju pārsteigti un gatavi pasaulei parādīt to, ko es darīju. Tāpēc es nonācu starp tīmeklī un atradu nelielu subreddit ar nosaukumu “playmygame”. Es uzrakstīju īsu kopsavilkumu un ievietoju to (ps ieraksta komentāros jūs skaidri redzat, ka es uzsveru par sava servera spējām). Es pacietīgi gaidīju, tad HUZZAH! Bija pievienojies spēlētājs.

Spēlē mēs gājām viens otram šurpu turpu. Pa to laiku es stresoju un uztraucos, ko domā šis spēlētājs. Pēc tam, kad šis spēlētājs zaudēja visu savu dzīvi un tika palaists no spēles, kurā mēs bijām, es gaidīju, vai viņi atgriezīsies. Un viņi to darīja! Bet vēl labāk: spēlētājs iestatīja savu vārdu uz “ilikethisgame”. Manas acis kļuva platākas, un manī uzlija adrenalīns! Es biju laimīgākais zēns pasaulē.

Drīz citi spēlētāji pievienojās un daži atstāja komentārus par Reddit ziņu. Vairāk spēlētāju teica, ka viņiem spēle patika! Es biju ekstāzē. Tad es pārbaudīju, kā mans serveris turas augšā (15.08.) ...

Bija sajūta, ka kāds man būtu izsitis vēju. Vai tas bija īsts? Tam vajadzēja būt viltotam, es pie sevis nodomāju. Tikai divas spēles, un serverim ir grūti tās apstrādāt.

Es sāku domāt par to, kur es kļūdījos savā kodā. Es domāju, ka sadursmju noteikšanai noteikti ir jābūt sašaurinājumam. Bet es jau izmantoju kvadrātiņus, lai palīdzētu sašaurināt sadursmju noteikšanas caurbraukšanas reižu skaitu.

Man bija jāveic daži netīri darbi, tāpēc es izveidoju jaunu Digital Ocean serveri, ko izmantot kā savu attīstības serveri. Pēc tam es uz laiku pilnībā atspējoju sadursmju noteikšanu un redzēju, ka problēma joprojām pastāv.

Labi - ja sadursmju noteikšana nebija problēma, kas tad vēl varētu būt?

Es domāju par to, cik daudz informācijas es katru sekundi no servera sūtīju katram klientam. Man bija šī apraides funkcija, kas ik pēc 22 milisekundēm katram klientam nosūtīja spēles stāvokli. Šajā funkcijā es nevajadzīgi filtrēju klienta vietējo spēlētāju allPlayersīpašumā, lai tikai ievietotu vietējo atskaņotāju savā īpašumā. Tātad, es ne tikai ievietoju for ciklu (filtrēšanu) citā ciklā (apraide katram klientam), bet arī pielāgoju datus, kas katram klientam jānosūta ar šo apraides funkciju.

Šī pielāgošana nebija nepieciešama. Man vienkārši jāspēj nosūtīt spēles stāvoklis visiem bez pielāgošanas. Visiem vajadzētu iegūt vienādus datus (un datus nevajadzētu pielāgot konkrētam klientam). Tam vajadzēja būt procesora apēstā vietai. Tāpēc es optimizēju šo funkciju, nospiedu to līdz dev serverim un pārbaudīju CPU diagrammu. Nav labojumu.

Ar savu nezināšanu es sāku sevi pārliecināt, ka ~ 10–20 spēlētāji uz vienu galveno serveri ir labi. Kā es varu nonākt pie šāda secinājuma? Nu, mana ārkārtējā pārliecība par savām tehniskajām spējām mani acīmredzami aklināja no realitātes. Es paklupu uz ierakstu, kur agar.io veidotājs teica, ka viņa 1 pamata serveris spēj apstrādāt aptuveni 190 spēlētājus. Es ātri no tā izrāvos.

Nākamais vaininieks, kuru biju ierindojis rindā, bija: socket.io. Es izmantoju socket.io, lai pārvaldītu reāllaika saziņu starp klientu un serveri. Es biju dzirdējis jau iepriekš, ka socket.io nebija tik viegls kā citas alternatīvas.

Dienas laikā, ja vēlaties asinhroni nosūtīt ziņojumu, jums bija jāievieš sava veida uzlaušana: garas vēlēšanas vai zibatmiņas ligzdas. Tas notika tāpēc, ka ne visas tīmekļa pārlūkprogrammas atbalstīja tīmekļa ligzdas. Bet lielākā daļa pārlūkprogrammu tagad piedāvā vietējo atbalstu. Bet, lai socket.io izveidotu savienojumu, vispirms tas tiek darīts, izmantojot kādu no minētajiem pieejamajiem hakeriem, un pēc tam jaunina savienojumu, ja klients atbalsta labāku veidu. Pat ja tīmekļa ligzdas jau tiek plaši atbalstītas. Šī pieeja notiek uz CPU un atmiņas rēķina. Bet ne tik daudz, kā biju domājis ...

Es pārlecu tiešsaistē un naivi ierakstīju Google “socket io cpu problem”. Pirmie pāris rezultāti tika nosaukti “Node.js - kā atkļūdot Node + Socket.io CPU problēmas - servera kļūda” un “Node.js - Socket.io mezgla serveris, izmantojot lielu procesoru - kaudzes pārpilde”. Manas acis iedegās. Mani nomierināja, ka tas ir vaininieks manai problēmai. Bet es noklikšķināju uz pirmā raksta, un autors minēja, ka viņš nodarbojas ar ~ 1500 vienlaicīgiem kontaktligzdu savienojumiem. Es neesmu matemātikas specialiste, bet 20 spēlētāji ir ievērojami mazāk nekā 1500 spēlētāji.

Vienkārši par to, es pārslēdzu savu servera puses Node lietotni, lai izmantotu sīkas tīmekļa ligzdas, pēc tam pārslēdzu klienta puses Node lietotni, lai izmantotu vietējo tīmekļa ligzdas atbalstu tieši pārlūkprogrammā. Es uzstāju izmaiņas līdz dev serverim un pārbaudīju CPU diagrammu. Nav labojumu.

Mana morāle visu laiku bija zema. Es sāku raustīties katru reizi, kad man bija jāpārbauda saplēstā procesora diagramma. Es domāju, ka es nekad nedabūšu to zilo līniju, lai pārstātu bēgt no manis. Šī bija vienīgā reize, kad es jutos pilnīgi nespējīga tikt galā ar kādu tehnisku uzdevumu. Bet tad tas notika ...

Kad es kaut ko pamanīju, es sēdēju pie centrālā procesora grafika, kas gremdējās savās ciešanās. Nav svarīgi, cik pilnas spēles notiek vai cik cieši kopā tās visas tiek uzsāktas. Procesors nepārtraukti pieauga nemainīgā ātrumā. Es nekad nebiju uzturējies pietiekami ilgi, lai to novērotu. Atmiņas noplūde!

Es skenēju kodu pa rindai pa rindai, meklējot kļūdu (kas man bija jādara pašā sākumā). Tur tas bija.

Manā spēlē notikums ir objekts, kas uztver informāciju par tādām lietām kā spēlētāju nāve, palielināšanās un sadursmes. Tātad notikums tiek izveidots katru reizi, kad notiek kāda no šīm lietām.

Man ir šī cilpa, kas iet cauri katram notikumam un to atjaunina. To sauc ik pēc 16 ms. Pēc tam, kad notikums ir izpildījis savu pienākumu, to paredzēts dzēst. Atslēgvārdi: "vajadzēja."

Bingo. Man bija uzkrāta atmiņa, kā arī arvien vairāk nevajadzīgu ciklu piespēļu. Ievietoju koda rindiņu un voila!

Milzīga atvieglojuma nopūta.

Mans nākamais uzdevums ir redzēt, cik spēles (4 spēlētāji vienā spēlē) viens serveris var vienmērīgi atbalstīt. (Es zinu tās vismaz 12 spēles, bet vēl neesmu mēģinājis). Tagad, kad es zinu, ka notikumu skaitam ir milzīga ietekme uz procesoru ... kas notiks ražošanā, kad visi spēlētāji katru sekundi atlaidīs pastiprināšanas, sadursmes un nāves gadījumus? Mani testi to nav ņēmuši vērā.

Turklāt pēc tam, kad šī ziņa kļūs vīrusu un mana spēle sekos tam, man būs ātri jāsamazina pieejamo serveru skaits. Es izveidošu šo tēmu par nākamo ierakstu kopā ar: “Kā knckout.io pieauga līdz miljoniem spēlētāju.” Sekojiet man šeit, lai saņemtu atjauninājumus. :)