Megapack: Si Factorio zgjidhi problemin me shumë lojtarë me 200 lojtarë

Megapack: Si Factorio zgjidhi problemin me shumë lojtarë me 200 lojtarë
Në maj të këtij viti kam marrë pjesë si lojtar në Ngjarjet e KatherineOfSky MMO. Vura re se kur numri i lojtarëve arrin një numër të caktuar, çdo pak minuta disa prej tyre “bien”. Për fatin tuaj (por jo për mua), unë isha një nga ata lojtarë gjithmonedhe me një lidhje të mirë. E mora si një sfidë personale dhe fillova të kërkoja shkaqet e problemit. Pas tre javësh korrigjimi, testimi dhe rregullimi, defekti më në fund rregullohet, por udhëtimi nuk ka qenë edhe aq i lehtë.

Problemet në lojërat me shumë lojtarë janë shumë të vështira për t'u gjetur. Ato zakonisht ndodhin nën parametra shumë specifikë të rrjetit dhe nën gjendje shumë specifike të lojës (në këtë rast, mbi 200 lojtarë). Dhe edhe kur një problem mund të riprodhohet, ai nuk mund të korrigjohet siç duhet, sepse futja e pikave të ndërprerjes ndalon lojën, prish kohëmatësit dhe zakonisht shkakton ndërprerjen e lidhjes për shkak të një afati kohor. Por falë këmbënguljes dhe një mjeti të mrekullueshëm të quajtur i ngathët Unë arrita të kuptoj se çfarë po ndodh.

Shkurtimisht, për shkak të një gabimi dhe zbatimi jo të plotë të simulimit të gjendjes së vonesës, klienti ndonjëherë gjendej në një situatë ku duhej të dërgonte një paketë rrjeti në një cikël orësh, të përbërë nga veprime të hyrjes së lojtarit për zgjedhjen e afërsisht 400 entiteteve të lojës ( ne e quajmë atë një "megapaketë"). Pas kësaj, serveri jo vetëm që duhet të marrë saktë të gjitha këto veprime hyrëse, por edhe t'i dërgojë ato te të gjithë klientët e tjerë. Nëse keni 200 klientë, kjo shpejt bëhet problem. Kanali në server bllokohet shpejt, duke rezultuar në humbje të paketave dhe një kaskadë paketash të rikërkuara. Shtyrja e veprimeve të hyrjes bën që më shumë klientë të fillojnë të dërgojnë megapaketa dhe orteku i tyre bëhet edhe më i fortë. Klientët e suksesshëm arrijnë të rikuperohen, të gjithë të tjerët bien.

Megapack: Si Factorio zgjidhi problemin me shumë lojtarë me 200 lojtarë
Problemi ishte mjaft thelbësor dhe m'u deshën 2 javë për ta rregulluar. Është mjaft teknike, kështu që unë do t'i shpjegoj detajet e lëngshme teknike më poshtë. Por së pari, duhet të dini se që nga versioni 0.17.54, i lëshuar më 4 qershor, përballë problemeve të përkohshme të lidhjes, multiplayer-i është bërë më i qëndrueshëm dhe fshehja e vonesës është shumë më pak e ngarkuar (më pak frenim dhe teleportim). Gjithashtu, kam ndryshuar mënyrën e fshehjes së vonesave luftarake dhe shpresoj se kjo do t'i bëjë ato pak më të buta.

Paketa Mega me shumë lojtarë - Detaje teknike

Për ta thënë thjesht, multiplayer në një lojë funksionon kështu: të gjithë klientët simulojnë gjendjen e lojës duke marrë dhe dërguar vetëm hyrjen e lojtarit (të quajtur "veprimet hyrëse" Veprimet hyrëse). Detyra kryesore e serverit është transferimi Veprimet hyrëse dhe duke siguruar që të gjithë klientët të kryejnë të njëjtat veprime në të njëjtin cikël. Ju mund të lexoni më shumë rreth kësaj në postim. FFF-149.

Meqenëse serveri duhet të marrë vendime për veprimet që duhet të ndërmarrë, veprimet e lojtarit lëvizin përgjatë shtegut të mëposhtëm: veprimi i lojtarit -> klienti i lojës -> rrjeti -> serveri -> rrjeti -> klienti i lojës. Kjo do të thotë që çdo veprim i lojtarit kryhet vetëm pasi të ketë bërë një rrugë vajtje-ardhje përmes rrjetit. Për shkak të kësaj, loja do të dukej tmerrësisht e ngadaltë, kështu që pothuajse menjëherë pas shfaqjes së multiplayerve në lojë, u prezantua një mekanizëm për fshehjen e vonesave. Fshehja e vonesës simulon hyrjen e lojtarit pa marrë parasysh veprimet e lojtarëve të tjerë dhe vendimmarrjen e serverit.

Megapack: Si Factorio zgjidhi problemin me shumë lojtarë me 200 lojtarë
Factorio ka një gjendje loje gjendja e lojës është gjendja e plotë e hartës, lojtarit, entiteteve dhe gjithçkaje tjetër. Simulohet në mënyrë deterministe në të gjithë klientët bazuar në veprimet e marra nga serveri. Gjendja e lojës është e shenjtë dhe nëse ndonjëherë fillon të ndryshojë nga serveri ose ndonjë klient tjetër, atëherë ndodh desinkronizimi.

Me përjashtim të gjendja e lojës kemi një gjendje vonese Gjendja e vonesës. Ai përmban një nëngrup të vogël të gjendjes kryesore. Gjendja e vonesës nuk është e shenjtë dhe thjesht përfaqëson një pamje të asaj se si do të duket gjendja e lojës në të ardhmen bazuar në inputet nga lojtari Veprimet hyrëse.

Për ta bërë këtë, ne mbajmë një kopje të gjeneruar Veprimet hyrëse në radhën e vonesës.

Megapack: Si Factorio zgjidhi problemin me shumë lojtarë me 200 lojtarë
Kjo do të thotë, në fund të procesit në anën e klientit, fotografia duket diçka si kjo:

  1. Aplikoni Veprimet hyrëse të gjithë lojtarët për të gjendja e lojës mënyra se si këto veprime hyrëse janë marrë nga serveri.
  2. Hiqni gjithçka nga radha e vonesës Veprimet hyrëse, të cilat, sipas serverit, tashmë janë aplikuar gjendja e lojës.
  3. hequr Gjendja e vonesës dhe rivendoseni në mënyrë që të duket saktësisht njësoj si gjendja e lojës.
  4. Aplikoni të gjitha veprimet nga radha e vonesës deri në Gjendja e vonesës.
  5. Në bazë të të dhënave gjendja e lojës и Gjendja e vonesës ia jep lojën lojtarit.

E gjithë kjo përsëritet në çdo rrahje.

Shume e veshtire? Mos u relaksoni, kjo nuk është e gjitha. Për të kompensuar lidhjet jo të besueshme në internet, ne kemi krijuar dy mekanizma:

  • Ticks skipped: kur serveri vendos këtë Veprimet hyrëse do të ekzekutohet në takt të lojës, atëherë nëse nuk ka marrë Veprimet hyrëse ndonjë lojtar (për shembull, për shkak të një vonese të shtuar), ai nuk do të presë, por do ta informojë këtë klient "Unë nuk kam marrë parasysh tuajin Veprimet hyrëse, do të përpiqem t'i shtoj në shiritin tjetër. Kjo është bërë në mënyrë që për shkak të problemeve me lidhjen (ose me kompjuterin) të një lojtari, përditësimi i hartës të mos ngadalësohet për të gjithë të tjerët. Vlen të theksohet se Veprimet hyrëse nuk injorohen, por thjesht shtyhen.
  • Vonesa e plotë vajtje-ardhje: Serveri përpiqet të hamendësojë se cili është vonesa e vajtje-ardhjes ndërmjet klientit dhe serverit për secilin klient. Çdo 5 sekonda, ai negocion një vonesë të re me klientin sipas nevojës (në varësi të mënyrës se si është sjellë lidhja në të kaluarën) dhe rrit ose ul vonesën e udhëtimit vajtje-ardhje në përputhje me rrethanat.

Në vetvete, këta mekanizma janë mjaft të thjeshtë, por kur përdoren së bashku (gjë që ndodh shpesh me problemet e lidhjes), logjika e kodit bëhet e vështirë për t'u menaxhuar dhe me shumë raste të skajeve. Përveç kësaj, kur këta mekanizma hyjnë në lojë, serveri dhe radha e vonesës duhet të zbatojnë saktë një speciale Veprimi i hyrjes i quajtur StopMovementInTheNextTick. Falë kësaj, në rast të problemeve të lidhjes, personazhi nuk do të vrapojë më vete (për shembull, nën një tren).

Tani më duhet t'ju shpjegoj se si funksionon përzgjedhja e entitetit. Një nga llojet e kaluar Veprimi i hyrjes është një ndryshim në gjendjen e përzgjedhjes së një entiteti. Ai u tregon të gjithëve mbi cilin entitet lojtari ka qëndruar pezull me miun. Siç mund ta shihni, ky është një nga veprimet hyrëse më të shpeshta të dërguara nga klientët, kështu që për të kursyer gjerësinë e brezit, ne e kemi optimizuar atë në mënyrë që të zërë sa më pak hapësirë. Kjo zbatohet në këtë mënyrë: kur çdo entitet zgjidhet, në vend që të ruajë koordinatat e hartës absolute dhe me saktësi të lartë, loja ruan një kompensim relativ me saktësi të ulët nga përzgjedhja e mëparshme. Kjo funksionon mirë sepse zgjedhja e miut zakonisht ndodh shumë afër zgjedhjes së mëparshme. Kjo krijon dy kërkesa të rëndësishme: Veprimet hyrëse nuk duhet të anashkalohet kurrë dhe duhet bërë në rendin e duhur. Këto kërkesa plotësohen për gjendja e lojës. Por që nga detyra gjendje latente në "dukje mjaft mirë" për lojtarin, ata nuk janë të kënaqur në gjendjen e vonesës. Gjendja e vonesës nuk merr parasysh shumë raste kufitarelidhur me kapërcimin e orëve dhe ndryshimin e vonesave të transmetimit vajtje-ardhje.

Tashmë mund ta merrni me mend se ku po shkon kjo. Më në fund po fillojmë të shohim shkaqet e problemit të megapaketave. Rrënja e problemit është se logjika e përzgjedhjes së entitetit mbështetet Gjendja e vonesës, dhe kjo gjendje nuk përmban gjithmonë informacionin e saktë. Pra, megapaketa gjenerohet si kjo:

  1. Lojtari po përballet me probleme lidhjeje.
  2. Mekanizmat për kapërcimin e cikleve dhe rregullimin e vonesës së transmetimit vajtje-ardhje hyjnë në lojë.
  3. Radha e gjendjes së vonesës nuk i merr parasysh këto mekanizma. Kjo bën që disa veprime të hiqen para kohe ose të ekzekutohen në rendin e gabuar, duke rezultuar në një gabim Gjendja e vonesës.
  4. Lojtari nuk ka asnjë problem lidhjeje dhe simulon deri në 400 cikle për të kapur hapin me serverin.
  5. Në çdo cikël, një veprim i ri gjenerohet dhe përgatitet për t'u dërguar në server, duke ndryshuar përzgjedhjen e entitetit.
  6. Klienti dërgon një megapaketë prej 400+ ndryshimesh të përzgjedhjes së entitetit në server (dhe me veprime të tjera: gjendja e shkrepjes, gjendja e ecjes etj. gjithashtu vuan nga ky problem).
  7. Serveri merr 400 veprime hyrëse. Meqenëse nuk lejohet të kapërcehet një veprim i vetëm i hyrjes, ai udhëzon të gjithë klientët të kryejnë këto veprime dhe i dërgon ato përmes rrjetit.

Ironia është se një mekanizëm i krijuar për të ruajtur gjerësinë e brezit rezultoi në pako të mëdha rrjeti.

Ne e kemi zgjidhur këtë problem duke rregulluar të gjitha rastet e skajeve të përditësimit dhe mbështetjen e vonesës së radhës. Edhe pse u desh mjaft kohë, ia vlente ta rregulloje atë në fund në vend që të mbështetesh në hakmarrje të shpejtë.

Burimi: www.habr.com

Shto një koment