Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija

Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
Softver kao usluga, Infrastruktura kao usluga, Platforma kao usluga, Komunikaciona platforma kao usluga, Video konferencije kao usluga, a šta je sa Cloud Gamingom kao uslugom? Već je bilo nekoliko pokušaja stvaranja igrica u oblaku (Cloud Gaming), kao što je Stadia, koju je nedavno pokrenuo Google. Stadia nije novo u WebRTC-u, ali mogu li drugi koristiti WebRTC na isti način?

Thanh Nguyen je odlučio testirati ovu mogućnost na svom projektu otvorenog koda CloudRetro. CloudRetro je baziran na Pionu, popularno WebRTC biblioteka zasnovana na Go (hvala Shownu od razvojnog tima Pion za njihovu pomoć oko ovog članka). U ovom članku Thanh daje pregled arhitekture svog projekta, a također govori o tome šta je korisno naučio i sa kakvim se izazovima susreo tokom rada.

ulazak

Prošle godine, kada je Google najavio Stadia, bio sam oduševljen. Ideja je toliko jedinstvena i inovativna da sam se stalno pitao kako je to uopće moguće sa postojećim tehnologijama. Želja da bolje razumijem ovu temu potaknula me je da kreiram vlastitu verziju igre u oblaku otvorenog koda. Rezultat je bio jednostavno fantastičan. U nastavku bih želio podijeliti proces rada na svom godišnjem projekat.

TLDR: kratka verzija slajda sa istaknutim detaljima

Zašto je igranje u oblaku budućnost

Vjerujem da će Cloud Gaming uskoro postati nova generacija ne samo igara, već i drugih oblasti informatike. Igranje u oblaku je vrhunac klijent/server modela. Ovaj model maksimizira backend upravljanje i minimizira rad frontenda tako što hostuje logiku igre na udaljenom serveru i prenosi slike/audio na klijenta. Server obavlja tešku obradu tako da klijent više ne podliježe hardverskim ograničenjima.

Google Stadia vam u osnovi omogućava igranje AAA igre (tj. high-end blockbuster igre) na interfejsu kao što je YouTube. Ista metodologija se može primijeniti na druge teške offline aplikacije kao što su operativni sistem ili 2D/3D grafički dizajn itd. tako da ih možemo stabilno pokrenuti na uređajima niskih specifikacija na različitim platformama.

Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
Budućnost ove tehnologije: zamislite da je Microsoft Windows 10 pokrenut u Chrome pretraživaču?

Igranje u oblaku je tehnički teško

Igranje je jedno od onih rijetkih područja gdje je potrebna stalna brza reakcija korisnika. Ako povremeno naiđemo na kašnjenje od 2 sekunde prilikom klikanja na stranicu, to je prihvatljivo. Video prijenosi uživo obično kasne nekoliko sekundi, ali i dalje nude priličnu količinu upotrebljivosti. Međutim, ako igra često kasni 500ms, jednostavno nije moguće igrati. Naš cilj je postići izuzetno malo kašnjenje kako bi jaz između inputa i medija bio što manji. Stoga, tradicionalni pristup streamingu videa ovdje nije primjenjiv.

Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
Opšti predložak igre u oblaku

Projekat otvorenog koda CloudRetro

Odlučio sam da napravim probni uzorak igre u oblaku da vidim da li je sve to moguće uz tako ozbiljna mrežna ograničenja. Odabrao sam Golang za dokaz koncepta jer je to jezik koji mi je najpoznatiji i koji se dobro uklapa za ovu implementaciju iz mnogih drugih razloga, kako sam kasnije saznao. Go je jednostavan i razvija se vrlo brzo; Kanali u Go-u su odlični za upravljanje višenitnošću.

Projekat CloudRetro.io je usluga za igranje u oblaku otvorenog koda za retro igranje. Cilj projekta je donijeti najudobnije iskustvo igranja tradicionalnim retro igrama i dodati multiplayer.
Više o projektu možete saznati ovdje: https://github.com/giongto35/cloud-game.

CloudRetro funkcionalnost

CloudRetro koristi retro igre da pokaže snagu igranja u oblaku. To vam omogućava da steknete mnogo jedinstvenih iskustava u igrici.

  • Prenosivost igre
    • Trenutna reprodukcija prilikom otvaranja stranice; nije potrebno preuzimanje i instalacija
    • Radi na mobilnom pretraživaču tako da za pokretanje nije potreban softver

  • Sesije igre se mogu dijeliti na više uređaja i pohraniti u oblak za sljedeću prijavu
  • Igru možete streamati ili je možete igrati s nekoliko korisnika odjednom:
    • Crowdplay kao TwitchPlayPokemon, samo više na više platformi i više u realnom vremenu
    • Offline igre online. Mnogi korisnici mogu igrati bez podešavanja mreže. Samurai Shodown se sada može igrati sa 2 igrača preko CloudRetro mreže

    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    Demo verzija online igre za više igrača na različitim uređajima

    Infrastruktura

    Zahtjevi i tehnološki niz

    Ispod je lista zahtjeva koje sam postavio prije početka projekta.

    1. Jedan igrač
    Ovaj zahtjev možda ovdje ne izgleda previše važan i očigledan, ali to je jedan od mojih ključnih zaključaka, drži igre u oblaku što dalje od tradicionalnih streaming servisa. Ako se fokusiramo na igru ​​za jednog igrača, možemo se riješiti centraliziranog servera ili CDN-a jer ne moramo streamati do masa. Umjesto učitavanja tokova na server za unos ili prosljeđivanja paketa na centralizirani WebSocket server, tokovi usluga se strimuju direktno korisniku putem WebRTC konekcije ravnopravnih korisnika.

    2. Medijski tok niske latencije
    Kada čitam o Stadiji, često vidim da se WebRTC spominje u nekim člancima. Shvatio sam da je WebRTC izvanredna tehnologija i odlična je za korištenje u igricama u oblaku. WebRTC je projekt koji web pretraživačima i mobilnim aplikacijama pruža komunikaciju u realnom vremenu putem jednostavnog API-ja. Pruža peer-to-peer konekciju, optimiziran je za medije i ima ugrađene standardne kodeke kao što su VP8 i H264.

    Dao sam prioritet pružanju najboljeg mogućeg korisničkog iskustva u odnosu na održavanje grafike visokog kvaliteta. Neki gubici su dozvoljeni u algoritmu. Google Stadia ima dodatni korak za smanjenje veličine slike na serveru, a okviri se povećavaju na viši kvalitet prije nego što se proslijede kolegama.

    3. Distribuirana infrastruktura sa geografskim usmjeravanjem
    Bez obzira na to koliko su optimizirani algoritam kompresije i kod, mreža je i dalje odlučujući faktor koji najviše doprinosi kašnjenju. Arhitektura bi trebala imati mehanizam za uparivanje servera najbližeg korisniku kako bi se smanjilo vrijeme povratnog putovanja (RTT). Arhitektura bi trebala imati 1 koordinatora i nekoliko streaming servera distribuiranih širom svijeta: Zapad SAD, Istok SAD, Evropa, Singapur, Kina. Svi streaming serveri moraju biti potpuno izolirani. Sistem može prilagoditi svoju distribuciju kada se server pridruži ili napusti mrežu. Stoga, uz veliki promet, dodavanje dodatnih servera omogućava horizontalno skaliranje.

    4. Kompatibilnost pretraživača
    Igre u oblaku su najbolje kada od korisnika zahtijevaju minimum. To znači da je moguće pokrenuti u pretraživaču. Preglednici pomažu korisnicima da iskustvo igranja bude što ugodnije, tako što ih štede od instaliranja softvera i hardvera. Preglednici također pomažu u pružanju višeplatformskih verzija za mobilne i desktop verzije. Na sreću, WebRTC je dobro podržan u raznim pretraživačima.

    5. Jasno razdvajanje interfejsa igre i servisa
    Na uslugu igranja u oblaku gledam kao na platformu. Svako bi trebao biti u mogućnosti da poveže bilo šta na platformu. Sada sam se integrisao LibRetro sa uslugom igara u oblaku jer LibRetro nudi prekrasno sučelje emulatora igre za retro igre kao što su SNES, GBA, PS.

    6. Prostorije za multiplayer, masovnu igru ​​i vanjsko povezivanje (deep-link) sa igrom
    CloudRetro podržava mnoge nove igre kao što su CrowdPlay i Online MultiPlayer za retro igre. Ako nekoliko korisnika otvori istu dubinsku vezu na različitim računarima, vidjet će da radi ista igra i čak će joj se moći pridružiti.

    Štaviše, stanja igre se pohranjuju u pohranu u oblaku. Ovo omogućava korisnicima da nastave igru ​​u bilo kojem trenutku na bilo kojem drugom uređaju.

    7. Horizontalno skaliranje
    Kao i svaki SAAS danas, igranje u oblaku mora biti dizajnirano tako da bude horizontalno skalabilno. Dizajn koordinator-radnik vam omogućava da dodate više radnika kako biste opsluživali više prometa.

    8. Nije vezan za jedan oblak
    CloudRetro infrastrukturu hostuju različiti provajderi oblaka (Digital Ocean, Alibaba, prilagođeni provajder) za različite regione. Omogućavam pokretanje u infrastrukturnom Docker kontejneru i konfiguriram mrežne postavke pomoću bash skripte kako bih izbjegao ovisnost o jednom dobavljaču oblaka. Kombinujući ovo sa NAT Traversal-om u WebRTC-u, možemo imati fleksibilnost da primenimo CloudRetro na bilo kojoj platformi u oblaku, pa čak i na bilo kojoj mašini korisnika.

    Arhitektonsko projektovanje

    radnik: (ili gore spomenuti streaming server) umnožava igre, pokreće cevovod za kodiranje i prenosi kodirane medije korisnicima. Worker instance su distribuirane po cijelom svijetu i svaki radnik može istovremeno upravljati više korisničkih sesija.

    Koordinator: je odgovoran za uparivanje novog korisnika sa najprikladnijim streaming radnikom. Koordinator komunicira sa radnicima putem WebSocketa.

    Pohrana stanja igre: centralno udaljeno skladište za sva stanja igre. Ova pohrana pruža važne funkcije kao što je daljinsko spremanje/učitavanje.

    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    CloudRetro arhitektura najvišeg nivoa

    Custom Script

    Kada novi korisnik otvori CloudRetro u koracima 1 i 2 prikazanim na donjoj slici, koordinator se, zajedno sa listom dostupnih radnika, traži na prvoj stranici. Nakon toga, u koraku 3, klijent izračunava kašnjenja za sve kandidate koristeći HTTP ping zahtjev. Ova lista kašnjenja se zatim šalje nazad koordinatoru kako bi on mogao odrediti najprikladnijeg radnika koji će služiti korisniku. Korak 4 ispod kreira igru. WebRTC streaming veza se uspostavlja između korisnika i dodijeljenog radnika.
    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    Prilagođena skripta nakon dobijanja pristupa

    Šta je unutar radnika

    Cjevovodi za igre i striming se pohranjuju unutar radnika u izolaciji i tamo razmjenjuju informacije preko sučelja. Trenutno se ova komunikacija odvija prijenosom podataka u memoriju preko golang kanali u istom procesu. Sljedeći cilj je segregacija, tj. samostalno pokretanje igre u drugom procesu.

    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    Interakcija radničkih komponenti

    Glavne komponente:

    • WebRTC: komponenta klijenta koja prihvaća korisnički unos i izlazi kodirani medij sa servera.
    • Emulator igre: komponenta igre. Zahvaljujući Libretro biblioteci, sistem je u mogućnosti da pokrene igru ​​unutar istog procesa i interno presreće medijski i ulazni tok.
    • Okviri u igri se snimaju i šalju u koder.
    • Koder slike/audio: cevovod za kodiranje koji prima medijske okvire, kodira ih u pozadini i emituje kodirane slike/audio.

    Реализация

    CloudRetro se oslanja na WebRTC kao tehnologiju okosnice, pa sam prije nego što uđem u detalje implementacije Golang-a odlučio govoriti o samom WebRTC-u. To je nevjerovatan dio tehnologije koji mi je izuzetno pomogao u postizanju latencije ispod sekunde.

    WebRTC

    WebRTC je dizajniran za pružanje visokokvalitetnih peer-to-peer konekcija na izvornim mobilnim aplikacijama i preglednicima koristeći jednostavne API-je.

    NAT Traversal

    WebRTC je poznat po svojoj NAT Traversal funkcionalnosti. WebRTC je dizajniran za međusobnu komunikaciju. Njegova svrha je pronaći najprikladniji direktan put, izbjegavajući NAT gatewaye i firewall, za peer-to-peer kroz proces tzv. ICE. Kao dio ovog procesa, WebRTC API-ji pronalaze vašu javnu IP adresu koristeći STUN servere i prosljeđuju je na relejni server (TURN) kada se ne može uspostaviti direktna veza.

    Međutim, CloudRetro ne koristi u potpunosti ovu mogućnost. Njegove peer-to-peer veze ne postoje između korisnika, već između korisnika i cloud servera. Serverska strana modela ima manje ograničenja za direktnu komunikaciju nego tipični korisnički uređaj. Ovo vam omogućava da unapred otvorite dolazne portove ili direktno koristite javne IP adrese, pošto server nije iza NAT-a.

    Ranije sam želio da pretvorim projekat u platformu za distribuciju igara za Cloud Gaming. Ideja je bila da se kreatorima igara omogući da obezbede igre i resurse za striming. Korisnici bi direktno komunicirali sa provajderima. Na ovaj decentralizirani način, CloudRetro je samo medij za povezivanje resursa za streaming trećih strana s korisnicima, što ga čini skalabilnijim kada hosting više ne visi na njemu. Uloga WebRTC NAT Traversal-a je ovdje vrlo važna za olakšavanje inicijalizacije peer-to-peer konekcije na strujnim resursima treće strane, što kreatoru olakšava povezivanje na mrežu.

    Video kompresija

    Video kompresija je nezamjenjiv dio cevovoda i uvelike doprinosi glatkoći toka. Iako nije neophodno znati sve detalje VP8/H264 video kodiranja, razumijevanje koncepta pomaže u razumijevanju parametara brzine video strimovanja, otklanjanju grešaka u neočekivanom ponašanju i prilagođavanju latencije.

    Kompresija videa za streaming uslugu je izazovna jer algoritam mora osigurati da ukupno vrijeme kodiranja + vrijeme mrežnog prijenosa + vrijeme dekodiranja bude što je moguće manje. Osim toga, proces kodiranja mora biti dosljedan i kontinuiran. Neki kompromisi u kodiranju se ne primjenjuju - na primjer, ne možemo preferirati dugo vrijeme kodiranja u odnosu na manju veličinu datoteke i vrijeme dekodiranja, ili koristiti nedosljednu kompresiju.

    Ideja koja stoji iza video kompresije je da se eliminišu nepotrebni dijelovi informacija uz održavanje prihvatljivog nivoa vjernosti za korisnike. Osim kodiranja pojedinačnih statičkih okvira slike, algoritam zaključuje trenutni okvir iz prethodnog i sljedećeg, pa se šalje samo njihova razlika. Kao što možete vidjeti iz Pacman primjera, prenose se samo diferencijalne točke.

    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    Poređenje video okvira koristeći Pacman kao primjer

    Audio kompresija

    Slično, algoritam kompresije zvuka izostavlja podatke koje ljudi ne mogu percipirati. Opus je trenutno najbolji audio kodek. Dizajniran je da prenosi audio talas preko naređenog protokola datagrama kao što je RTP (Protokol transporta u realnom vremenu). Njegovo kašnjenje je manje nego kod mp3 i aac-a, a kvalitet je veći. Latencija je obično oko 5~66,5ms.

    Pion, WebRTC u Golangu

    Pijun je projekat otvorenog koda koji donosi WebRTC na Golang. Umjesto uobičajenog omota izvornih C++ WebRTC biblioteka, Pion je izvorna Golang WebRTC implementacija sa boljim performansama, Go integracijom i kontrolom verzija na WebRTC protokolima.

    Biblioteka također pruža streaming podataka s puno sjajnih ugrađenih modula s kašnjenjem manjim od sekunde. Ima vlastitu implementaciju STUN, DTLS, SCTP, itd. i malo eksperimentisanja sa QUIC-om i WebAssembly-om. Sama po sebi, ova biblioteka otvorenog koda je zaista dobar izvor učenja sa odličnom dokumentacijom, implementacijama mrežnih protokola i odličnim primjerima.

    Pion zajednica, koju vodi veoma strastveni kreator, prilično je živahna i ima dosta kvalitetnih rasprava o WebRTC-u. Ako ste zainteresovani za ovu tehnologiju, pridružite se http://pion.ly/slack - naučit ćete puno novih stvari.

    Pisanje CloudRetro na Golangu

    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    Radnička implementacija u Go

    Idi na kanale u akciji

    Sa prekrasnim dizajnom Go kanala, pitanja striminga događaja i istovremenosti su uvelike pojednostavljena. Kao na dijagramu, postoji nekoliko komponenti koje rade paralelno u različitim GoRoutinama. Svaka komponenta upravlja svojim stanjem i komunicira putem kanala. Golangova selektivna tvrdnja uzrokuje da se jedan atomski događaj obradi svaki put u igri (tik igre). To znači da za ovaj dizajn nije potrebno blokiranje. Na primjer, kada se korisnik sačuva, potrebna je potpuna snimka stanja igre. Ovo stanje mora ostati kontinuirano, prijavljivanje dok se spremanje ne završi. Tokom svake igre, backend može obraditi samo operaciju spremanja ili unosa, što proces čini sigurnim u niti.

    func (e *gameEmulator) gameUpdate() {
    for {
    	select {
    		case <-e.saveOperation:
    			e.saveGameState()
    		case key := <-e.input:
    			e.updateGameState(key)
    		case <-e.done:
    			e.close()
    			return
    	}
        }
    }

    ventilator-in / fan-out

    Ovaj Golang predložak je odličan za moj CrowdPlay i slučaj više igrača. Slijedeći ovaj obrazac, svi korisnički ulazi u istoj prostoriji ugrađeni su u središnji ulazni kanal. Mediji igre se zatim raspoređuju svim korisnicima u istoj prostoriji. Na taj način postižemo podjelu stanja igre između nekoliko sesija igre različitih korisnika.

    Igre u oblaku otvorenog koda na WebRTC-u: p2p, multiplayer, nulta latencija
    Sinhronizacija između različitih sesija

    Nedostaci Golanga

    Golang nije savršen. Kanal je spor. U poređenju sa blokiranjem, Go kanal je jednostavno lakši način za rukovanje istovremenim i streaming događajima, ali kanal ne pruža najbolje performanse. Ispod kanala postoji složena logika blokiranja. Stoga sam napravio neke prilagodbe implementacije ponovnom primjenom zaključavanja i atomskih vrijednosti prilikom zamjene kanala radi optimizacije performansi.

    Osim toga, Golangov sakupljač smeća je neupravljiv, što ponekad uzrokuje sumnjivo duge pauze. Ovo uvelike ometa aplikaciju za striming u realnom vremenu.

    COG

    Projekat koristi postojeću VP8/H264 open source Golang biblioteku za kompresiju medija i Libretro za emulatore igara. Sve ove biblioteke su samo omoti za C biblioteku u Go-u COG. Neki od nedostataka su navedeni u ovaj post Dave Cheney. Problemi sa kojima sam se suočio:

    • nemogućnost da se uhvati pad u CGO, čak i sa Golang RecoveryCrash;
    • nemogućnost identificiranja uskog grla u performansama kada ne možemo otkriti granularne probleme u CGO-u.

    zaključak

    Postigao sam svoj cilj pronalaženja usluga igranja u oblaku i kreiranja platforme koja mi pomaže da igram nostalgične retro igrice sa svojim prijateljima na mreži. Ovaj projekat ne bi bio moguć bez Pion biblioteke i podrške Pion zajednice. Izuzetno sam zahvalan na njegovom intenzivnom razvoju. Jednostavni API-ji koje pružaju WebRTC i Pion osigurali su besprijekornu integraciju. Moj prvi dokaz koncepta objavljen je iste sedmice, uprkos tome što nisam bio svjestan peer-to-peer (P2P) komunikacija unaprijed.

    Uprkos lakoći integracije, P2P striming je zaista veoma složena oblast u računarskoj nauci. Mora se nositi sa složenošću višegodišnjih mrežnih arhitektura kao što su IP i NAT da bi stvorio peer-to-peer sesiju. Dok sam radio na ovom projektu, stekao sam mnogo dragocjenog znanja o umrežavanju i optimizaciji performansi, pa preporučujem svima da pokušaju da naprave P2P proizvode koristeći WebRTC.

    CloudRetro služi za sve slučajeve upotrebe koje sam očekivao sa moje tačke gledišta kao retro igrač. Međutim, mislim da postoje mnoge oblasti u projektu koje mogu poboljšati, kao što je stvaranje mreže pouzdanijom i učinkovitijom, pružanje kvalitetnije grafike igara ili mogućnost dijeljenja igara između korisnika. Naporno radim na ovome. Molim vas pratite projekat i podrzi ga ako ti se dopada.

izvor: www.habr.com

Dodajte komentar