Shërbimi Cloud, infrastruktura si shërbim, platforma si shërbim, platforma komunikimi si shërbim, videokonferencat si shërbim, por çfarë është për lojërat në re si shërbim? Janë bërë disa përpjekje për krijimin e lojërave në re, si për shembull, Stadia, e cila u lançua së fundmi nga Google. Stadia , por a mund të përdorin të tjerët WebRTC njësoj?
Thanh Nguyen vendosi të verifikojë këtë mundësi në projektin e tij open-source CloudRetro. CloudRetro bazohet në Pion, popullore WebRTC e bazuar në Go (faleminderit nga grupi i zhvilluesve Pion për ndihmën në përgatitjen e këtij artikulli). Në këtë artikull, Thanh bën një pasqyrë të arkitekturës së projektit të tij dhe gjithashtu tregon se çfarë ka mësuar dhe me çfarë sfidash është përballur gjatë punës.
Hyrje
Vitin e kaluar, kur Google njoftoi Stadia, më goditi fort. Ideja është kaq unike dhe inovative saqë vazhdimisht e pyesja veten se si është e mundur një gjë e tillë me teknologjitë aktuale. Dëshira për të kuptuar më mirë këtë temë më nxiti të krijoja versionin tim open-source të lojës në re. Rezultati ishte thjesht fantastik. Më poshtë do doja të ndaja procesin e punës mbi projektin tim njëvjeçar .
TLDR: një version i shkurtër me pikat kryesore
Pse e ardhmja është për lojërat në re
Besoj se Cloud Gaming shumë shpejt do të bëhet brezi i ri jo vetëm i lojërave, por edhe i fushave të tjera të informatikës. Lojërat në re janë maja e modelit klient/server. Ky model maksimizon menaxhimin e backend-it dhe minimizon punën e frontend-it duke vendosur logjikën e lojës në një server të largët dhe duke transmetuar pamjet/audiot tek klienti. Serveri bën përpunimin e rëndë, prandaj klienti nuk është më i varur nga kufizimet harduerike.
Google Stadia, në thelb, lejon të luash në (dmth. lojërat e klasit më të lartë) në një ndërfaqe si YouTube. Të njëjtën metodologji mund të aplikohet edhe për aplikacione të tjera të rënda offline, si sistemi operativ ose dizajni grafik 2D/3D etj. që mund t'i ekzekutojmë në mënyrë të qëndrueshme në pajisje me karakteristika të ulta në platforma të ndryshme.

E ardhmja e kësaj teknologjie: imagjinoni nëse Microsoft Windows 10 do të punonte në shfletuesin Chrome?
Lojërat në re janë teknikisht të komplikuara
Gaming is one of those rare areas where a constant fast response from the user is required. If we occasionally experience a delay of 2 seconds when clicking on a page, that's acceptable. Live video streams typically lag a few seconds, but still provide enough convenience for use. However, if a game frequently lags by 500 ms, it's simply unplayable. Our goal is to achieve extremely low latency so that the gap between input and media is as small as possible. Therefore, the traditional approach to streaming video is not applicable here.

The general template for cloud gaming
Open-source project CloudRetro
I decided to create a test sample of cloud gaming to check whether it's possible given such strict network limitations. For the proof of concept, I chose Golang, as it's the language I'm most familiar with and well-suited for this implementation for many other reasons, as it turned out later. Go is simple and develops very quickly; channels in Go are great for managing multithreading.
Projekti – a cloud gaming service with open source for retro gaming. The goal of the project is to bring the most comfortable gaming experience to traditional retro games and add multiplayer functionality.
You can learn more about the project here: .
CloudRetro functionality
To showcase the full power of cloud gaming, retro games are used in CloudRetro. This allows for many unique gaming experiences.
- Game portability
- Instant playback when opening the page; no download or installation required
- Works in mobile browsers, so no software installation is needed to launch
- Gaming sessions can be jointly used on multiple devices and stored in the cloud for the next login
- The game can be streamed, or multiple users can play it simultaneously:
- Crowdplay like TwitchPlayPokemon, but more cross-platform and real-time
- Offline games online. Many users can play without network setup. In Samurai Shodown, 2 players can now play over the CloudRetro network

Demo version of multiplayer online games on different devicesInfrastruktura
Requirements and technology stack
Below is a list of requirements that I set before starting the project.
1. Një lojtar
Ky kërkesë mund të duket e thjeshtë dhe e qartë këtu, por është një nga përfundimet e mia kryesore; ajo lejon që lojërat në re të qëndrojnë sa më larg nga shërbimet tradicionale të transmetimit. Nëse përqendrohemi te loja për një lojtar, mund të heqim dorë nga një server i centralizuar ose një CDN, sepse nuk na nevojitet transmetimi për masat. Në vend që të ngarkojmë kanale në një server të gjerë ose të transferojmë paketa në një server të centralizuar WebSocket, kanalet shërbyese dërgohen drejtpërdrejt te përdoruesi përmes një lidhjeje peer-to-peer WebRTC.2. Të dhëna mediatike me vonesë të ulët
Ndërsa lexoj për Stadia, shpesh has në disa artikuj për të përmendur WebRTC. E kuptova që WebRTC është një teknologji e jashtëzakonshme, dhe ajo përshtatet shkëlqyeshëm për përdorim në lojërat në re. WebRTC është një projekt që ofron komunikim në kohë reale për shfletuesit dhe aplikacionet mobile përmes një API të thjeshtë. Ajo siguron një lidhje peer-to-peer, të optimizuar për media dhe ka kodekët standardë të integruar, si VP8 dhe H264.Kam dhënë përparësi sigurisë për një funksionim sa më komod të përdoruesve, sesa ruajtjes së cilësisë së lartë të grafikës. Në algoritëm janë të lejuara disa humbje. Në Google Stadia ka një hap shtesë për të zvogëluar madhësinë e imazhit në server dhe kadrot skalen në cilësi më të lartë para se t'i dërgohen nyjeve të peer-to-peer.
3. Infrastrukturë e shpërndarë me ruterim gjeografik
Pavarësisht nga sa i optimizuar është algoritmi i kompresimit dhe kodi, rrjeti mbetet një faktor vendimtar që kontribuon më së shumti në vonesë. Arkitektura duhet të ketë një mekanizëm bashkëlidhjeje me serverin më të afërt për përdoruesin për të reduktuar kohën e ndjeshmërisë (RTT). Arkitektura duhet të ketë 1 koordinues dhe disa servera transmetimi të shpërndarë në mbarë botën: Perëndimi i SHBA-së, Lindja e SHBA-së, Evropa, Singapori, Kina. Të gjitha serverat transmetues duhet të jenë plotësisht të izoluar. Sistemi mund të rregullojë shpërndarjen e tij kur serveri bashkohet me rrjetin ose largohet nga ai. Kështu, në kohë të mëdha trafiku, shtimi i serverave shtesë lejon që të bëhet shkallëzim horizontal.4. Përputhshmëri e shfletuesit
Lojrat e bulimeve shfaqen në mënyrën më të mirë kur kërkojnë minimalin nga përdoruesit. Kjo do të thotë se ka mundësi për ta bërë lojën në shfletues. Shfletuesit ndihmojnë në krijimin e një përvoje loje sa më të rehatshme për përdoruesit, duke i lirosh ata nga instalimi i pajisjeve software dhe hardware. Shfletuesit gjithashtu ndihmojnë në sigurimin e ndërveprueshmërisë mes versioneve mobile dhe desktop. Me fat, WebRTC mbështetet mjaft mirë në shfletues të ndryshëm.5. Ndarja e qartë e ndërfaqes së lojës dhe shërbimit
Unë e shoh shërbimin e lojërave në cloud si një platformë. Çdo kush duhet të ketë mundësinë për t'u lidhur me platformën për qualquer gjë. Aktualisht kam integruar me shërbimin e lojërave në cloud, sepse LibRetro ofron një ndërfaqe të bukur për emulatorët e lojërave retro si SNES, GBA, PS.6. Dhomat për multiplayer, crowd play dhe lidhjen e jashtme (deep-link) me lojën
CloudRetro mbështet shumë lloje të reja gameplay, si CrowdPlay dhe Online MultiPlayer për lojërat retro. Nëse disa përdorues hapin të njëjtin deep-link në kompjuterë të ndryshëm, ata do të shohin të njëjtën lojë të nisur dhe madje mund të bashkohen me të.Për më tepër, gjendjet e lojës ruhen në magazinën cloud. Kjo lejon përdoruesit të vazhdojnë lojën në çdo kohë në çdo pajisje tjetër.
7. Shkallëzimi horizontal
Si çdo SAAS, lojërat në cloud duhet të projektohen që të jenë horizontalisht të shkallëzueshme. Konstrukti "koordinator-punëtor" lejon shtimin e më shumë punëtorëve për të shërbyer një trafik më të madh.8. Asnjë varësi nga një cloud i vetëm
Infrastruktura CloudRetro është e vendosur në ofrues të ndryshëm cloud (Digital Ocean, Alibaba, ofrues i personalizuar) për rajone të ndryshme. Unë aktivizoj nisjen në kontejnerin Docker për infrastrukturën dhe konfiguroj parametrat e rrjetit me një skriptë bash për të evituar varësinë nga një ofrues i vetëm cloud. Duke e kombinuar këtë me NAT Traversal në WebRTC, ne mund të arrijmë fleksibilitetin për të shpërndarë CloudRetro në çdo platformë cloud dhe madje edhe në makinat e çdo përdoruesi.Dizajni arkitektonik
Pune: (ose server streaming, përmendur më lart) shumëfishon lojërat, nis linjën e kodimit dhe transmeton median e koduar te përdoruesit. Instancat e punonjësve janë të shpërndara në mbarë botën, dhe çdo punonjës mund të përballojë disa seanca përdoruesish në të njëjtën kohë.
Koordinatori: është përgjegjës për lidhjen e përdoruesit të ri me punonjësin më të përshtatshëm për transmetim. Koordinatori ndërvepron me punonjësit përmes WebSocket.
Magazina e gjendjeve të lojës: një magazinë centrale e largët për të gjitha gjendjet e lojës. Kjo magazinë ofron funksione të rëndësishme, si p.sh. ruajtje/ngarkim të largët.

Arkitektura e nivelit të lartë CloudRetroSkema e përdoruesit
Kur një përdorues i ri hap CloudRetro në hapat 1 dhe 2, që shihen në figurën më poshtë, kërkohet koordinatori me listën e punonjësve të disponueshëm në faqen e parë. Më pas, në hapin 3, klienti llogarit vonesat për të gjithë kandidatët me një kërkesë ping në HTTP. Kjo listë vonesash pastaj dërgohet përsëri te koordinatori, në mënyrë që ai të mund të përcaktojë punonjësin më të përshtatshëm për të shërbyer përdoruesin. Në hapin 4 më poshtë krijohet loja. Një lidhje transmetimi WebRTC vendoset mes përdoruesit dhe punonjësit të caktuar.

Skema e përdoruesit pas marrjes së qasjesÇfarë ndodhet brenda punonjësit
Pipelines e lojërave dhe transmetimit ruhet brenda punonjësit në mënyrë të izoluar dhe shkëmbejnë informacion përmes një interface. Aktualisht, kjo lidhje realizohet përmes transmetimit të të dhënave në memorje përmes në të njëtin proces. Qëllimi tjetër është segregaimi, pra ekzekutimi i pavarur i lojës në një proces tjetër.

Interaksioni i komponentëve të punonjësitKomponentët kryesorë:
- WebRTC: komponenti i klientit, që pranon hyrjen e përdoruesit dhe del median e koduar nga serveri.
- Emulatori i lojës: komponenti i lojës. Përmes bibliotekës Libretro, sistemi është i aftë të ekzekutojë lojën brenda të njëjtit proces dhe të kapë brendësisht median dhe fluksin e hyrjes.
- Kadrin e brendshëm të lojës kapet dhe dërgohet në kodues.
- Koduesi i imazhit/audios: linja e kodimit që merr kadrin e median, i kodon ata në sfond dhe del imazhe/audio të koduara.
Implementimi
CloudRetro mbështetet në WebRTC si teknologjinë kryesore, prandaj para se të thellohem në detajet e zbatimit në Golang, vendosa të flas për vetë WebRTC. Kjo është një teknologji fantastike që më ka ndihmuar shumë në arritjen e vonesës së transmetimit të të dhënave prej vetëm disa qindarken.
WebRTC
WebRTC është projektuar për të siguruar lidhje peer-to-peer me cilësi të lartë në aplikacione mobile native dhe në shfletues me anë të API-ve të thjeshta.
Shkalla e NAT Traversal
WebRTC është i njohur për funksionalitetin e tij NAT Traversal. WebRTC është projektuar për komunikim mes përdoruesve. Qëllimi i tij është të gjejë rrugën më të përshtatshme direkte, duke shmangur NAT-të dhe Firewall-et për lidhje peer-to-peer nëpërmjet një procesi të quajtur . Në kuadër të këtij procesi, API-të WebRTC gjejnë adresën tuaj IP publike me anë të serverëve STUN dhe e drejtojnë atë në një server retranslacioni (), kur një lidhje direkte nuk mund të vendoset.
Megjithatë, CloudRetro nuk e përdor plotësisht këtë mundësi. Lidhjet e tij peer-to-peer nuk ekzistojnë mes përdoruesve, por mes përdoruesve dhe serverëve cloud. Pjesa serverike e modelit ka më pak kufizime për lidhjen direkte sesa një pajisje zakonshme përdoruesi. Kjo lejon hapjen paraprake të porteve hyrëse ose përdorimin e adresave IP publike drejtpërdrejt, pasi serveri nuk ndodhet pas NAT-it.
Përpara, doja të ktheja projektin në një platformë shpërndarjeje lojërash për Cloud Gaming. Ideja ishte që t'u lejoja krijuesve të lojërave të ofronin lojëra dhe burime transmetimi. Përdoruesit do të interagonin direkt me ofruesit. Në një mënyrë të tillë decentralizimi, CloudRetro është thjesht një mjedis për lidhjen e burimeve të transmetimit nga palë të treta me përdoruesit, duke e bërë atë më të shkallëzueshëm, kur nuk ka më ngarkesë pritëse. Roli i NAT Traversal të WebRTC është shumë i rëndësishëm për lehtësimin e nismës së lidhjeve peer-to-peer në burime transmetimi nga palë të treta, duke e bërë më të thjeshtë lidhjen e krijuesit me rrjetin.
Kompresimi i videos
Kompresimi i videos është një pjesë e pandarë e pipeline-it që kontribuon në masë të madhe në rritjen e rrafshësisë së transmetimit. Edhe pse nuk është e nevojshme të dihen të gjitha detajet e kodimit të videos në VP8/H264, kuptimi i konceptit ndihmon në të kuptuarit e parametrave të shpejtësisë së videos në transmetim, në zgjidhjen e sjelljeve të papritura, dhe në konfigurimin e vonesave.
Kompresimi i videos për shërbimin e transmetimit është një detyrë e ndërlikuar, sepse algoritmi duhet të garantojë që koha totale e kodimit + koha e transmetimit në rrjet + koha e dekodimit të jetë sa më e vogël të jetë e mundur. Për më tepër, procesi i kodimit duhet të jetë i radhitur dhe i vazhdueshëm. Disa kompromis të ndërsjellë gjatë kodimit nuk janë të aplikueshëm – për shembull, nuk mund të preferojmë një kohë më të gjatë kodimi për një madhësi më të vogël skedari dhe kohë dekodimi, ose të përdorim kompresim të pashtjellohet.
Ideja e kompresimit të videos është të përjashtojë bitet e panevojshme të informacionit, duke ruajtur një nivel të pranueshëm saktësie për përdoruesit. Përveç kodimit të fotove statike individuale, algoritmi nxjerr për foton aktuale nga fotografia e mëparshme dhe ajo që vjen pas saj, kështu që dërgohet vetëm diferenca midis tyre. Siç shihet nga shembulli me Pacman, dërgohen vetëm piketat diferenciale.

Krahasimi i videokadrove me shembullin PacmanKompresimi i audios
Në mënyrë të ngjashme, algoritmi i kompresimit të audios heq të dhënat që nuk mund të perceptohen nga njeriu. Opus aktualisht është kodeku audio me performancën më të mirë. Ai është zhvilluar për të transmetuar valët audio përmes një protokolli të dërgueshëm, si RTP (Protokolli i Transportit në Kohë Reale). Vonesa e tij është më e ulët se ajo e mp3 dhe aac, dhe cilësia është më e lartë. Vonesa zakonisht është rreth 5~66.5 ms.
Pion, WebRTC në Golang
është një projekt me kod të hapur që sjell WebRTC në Golang. Në vend të mbështjelljes standarde të bibliotekave native C++ të WebRTC, Pion është një implementim native i WebRTC në Golang me performancë më të mirë, integrim me Go, si dhe kontrollin e versioneve në protokollet WebRTC.
Biblioteka gjithashtu ofron transmetim të dhënash me shumë module të shkëlqyera të integruara me vonesë më pak se një sekondë. Ajo ka zbatimin e saj të STUN, DTLS, SCTP etj. dhe disa eksperimente me QUIC dhe WebAssembly. Kjo bibliotekë open-source është në të vërtetë një burim shumë i mirë për mësim me dokumentacion të shkëlqyer, zbatim të protokolleve rrjet dhe shembuj të shkëlqyer.
Komuniteti Pion, i udhëhequr nga një krijues shumë pasionant, është mjaft i gjallë, aty zhvillohen shumë diskutime cilësore për WebRTC. Nëse jeni të interesuar për këtë teknologji, bashkohuni me – do të mësoni shumë gjëra të reja.
Shkrimi i CloudRetro në Golang

Zbatimi i punonjësit në GoKanalet Go në veprim
Falë dizajnit të bukur të kanaleve Go, problemet e transmetimit të ngjarjeve dhe paralelizmit thjeshtohen ndjeshëm. Ashtu si në diagram, disa komponentë punojnë paralelisht në GoRoutines të ndryshme. Çdo komponent menaxhon gjendjen e tij dhe komunikon përmes kanaleve. Deklarata selektive në Golang bën që të përpunojë një ngjarje atomike në çdo moment në lojë (game tick). Kjo do të thotë se për një dizajn të tillë nuk nevojitet bllokim. Për shembull, kur përdoruesi ruhet, nevojitet një snapshot i plotë i gjendjes së lojës. Kjo gjendje duhet të mbetet e vazhdueshme, duke kryer hyrjen deri sa ruajtja të përfundojë. Gjatë çdo game tick, backend mund të përpunojë vetëm operacionin e ruajtjes ose hyrjes, duke e bërë procesin të sigurt për rrjedhën.
func (e *gameEmulator) gameUpdate() { for { select { case <-e.saveOperation: e.saveGameState() case key := <-e.input: e.updateGameState(key) case <-e.done: e.close() return } } }Fan-in / Fan-out
Ky model i Golang është shumë i përshtatshëm për skenarin tim të përdorimit CrowdPlay dhe Many Player. Duke ndjekur këtë model, të gjithë hyrjet e përdoruesve në një dhomë përfshihen në një kanal hyrës qendror. Media e lojës më pas shpërndahet te të gjithë përdoruesit në një dhomë. Kështu, ne arrijmë ndarjen e gjendjes së lojës mes disa sesioneve të lojës të përdoruesve të ndryshëm.

Sinkronizimi mes seancave të ndryshmeDisavantazhet e Golang
Golang nuk është i përsosur. Kanali është i ngadalshëm. Në krahasim me bllokimin, kanali Go është thjesht një mënyrë më e lehtë për të trajtuar ngjarjet paralele dhe rrjedhëse, por kanali nuk ofron performancën më të mirë. Nën kanal ka një logjikë të komplikuar të bllokimit. Prandaj, unë bëra disa ndryshime në implementimin, duke rikuperuar bllokimet dhe vlerat atomike në zëvendësimin e kanaleve për optimizimin e performancës.
Për më tepër, garbage collector në Golang është i papërdorur, çka shkakton ndonjëherë ndalese të dyshimta të gjata. Kjo e pengon shumë funksionimin e aplikacioneve rrjedhëse në kohë reale.
CGO
Në projekt përdoret një bibliotekë ekzistuese VP8/H264 Golang me burim të hapur për kompresimin e mediave dhe Libretro për emulatorët e lojërave. Të gjitha këto biblioteka janë thjesht mbështjellese të bibliotekës C në Go duke përdorur . Disa nga disavantazhet janë renditur në . Problemet me të cilat u përballa:
- pamundësia për të kapur crash në CGO, madje edhe me ndihmën e Golang RecoveryCrash;
- pamundësia për të identifikuar ngushticën në performancë, kur nuk mund të zbulojmë probleme të detajuara në CGO.
Përfundim
Arrita qëllimin tim – kuptova shërbimet e lojërave në re dhe krijova një platformë që ndihmon në lojën e lojërave retro nostalgjike me miqtë e mi online. Krijimi i këtij projekti do të ishte e pamundur pa bibliotekën Pion dhe mbështetjen e komunitetit Pion. Jam shumë mirënjohës për zhvillimin e tij të intensifikuar. API-të e thjeshta që ofrojnë WebRTC dhe Pion siguruan një integrim të qetë. Prova ime e parë konceptuale u lëshua në të njëjtën javë, pavarësisht se nuk e dija paraprakisht për lidhjen një-pë- një (P2P).
Megjithatë, përveç thjeshtësisë së integrimit, transmetimi P2P është një fushë shumë e komplikuar në shkencën kompjuterike. Kjo i duhet të merret me kompleksitetin e arkitekturave të rrjetit për shumë vite, si IP dhe NAT për të krijuar një sesion peer-to-peer. Gjatë punës në këtë projekt kam akumuluar shumë njohuri të çmuara rreth rrjetit dhe optimizimit të performancës, prandaj rekomandoj të gjithëve të provojnë të ndërtuar produkte P2P duke përdorur WebRTC.
CloudRetro mbulon të gjitha skenarët e përdorimit që prisja, nga pikëpamja ime, si një lojtar retro. Megjithatë, besoj se ka shumë fusha në projekt që mund t'i përmirësoj, siç është të bëj rrjetin më të besueshëm dhe performues, të ofroj cilësi më të lartë grafike të lojërave, ose mundësinë për të ndarë lojërat midis përdoruesve. Po punoj shumë për këtë. Ju lutem, mbani sytë nga dhe mbështeteni nëse ju pëlqen.
Burimi: habr.com







