Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija

Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
Softver kao usluga, infrastruktura kao usluga, platforma kao usluga, komunikacijska platforma kao usluga, videokonferencija kao usluga, što je s igranjem u oblaku kao uslugom? Već je bilo nekoliko pokušaja stvaranja igranja u oblaku (Cloud Gaming), poput Stadije, koju je Google nedavno pokrenuo. Stadia nije novi u WebRTC-u, ali mogu li drugi koristiti WebRTC na isti način?

Thanh Nguyen odlučio je testirati ovu mogućnost na svom projektu otvorenog koda CloudRetro. CloudRetro se temelji na Pionu, popularan WebRTC biblioteka temeljena na Go (hvala prikazano od razvojnog tima Pion na pomoći u pripremi ovog članka). U ovom članku Thanh daje pregled arhitekture svog projekta, a također govori o tome koje je korisne stvari naučio i s kojim se izazovima susreo tijekom svog rada.

Ulazak

Prošle godine, kada je Google najavio Stadiju, to me oduševilo. Ideja je toliko jedinstvena i inovativna da sam se neprestano pitao kako je to uopće moguće s postojećom tehnologijom. Želja za boljim razumijevanjem ove teme potaknula me da napravim vlastitu verziju open-source igre u oblaku. Rezultat je bio jednostavno fantastičan. U nastavku želim podijeliti proces rada na svojoj godini projekt.

TLDR: kratka slajd verzija s istaknutim točkama

Zašto je igranje u oblaku budućnost

Vjerujem da će Cloud Gaming uskoro postati sljedeća generacija ne samo gaminga, već i drugih područja računalne znanosti. Igranje u oblaku je vrhunac modela klijent/poslužitelj. Ovaj model maksimizira pozadinsko upravljanje i minimizira rad sučelja hostingom logike igre na udaljenom poslužitelju i strujanjem slika/audija klijentu. Poslužitelj obavlja tešku obradu tako da klijent više nije prepušten na milost i nemilost hardverskim ograničenjima.

Google Stadia vam u biti omogućuje igranje AAA igre (tj. high-end blockbuster igre) na sučelju kao što je YouTube. Ista se metodologija može primijeniti na druge teške offline aplikacije kao što su operativni sustav ili 2D/3D grafički dizajn itd. tako da ih možemo dosljedno pokretati na uređajima s niskim specifikacijama na više platformi.

Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
Budućnost ove tehnologije: Zamislite da Microsoft Windows 10 radi u pregledniku Chrome?

Igranje u oblaku tehnički je zahtjevno

Igranje je jedno od onih rijetkih područja gdje je potreban stalan, brz odgovor korisnika. Ako povremeno naiđemo na kašnjenje od 2 sekunde kada kliknemo na stranicu, to je prihvatljivo. Video streamovi uživo obično kasne nekoliko sekundi, ali još uvijek nude razumnu upotrebljivost. Međutim, ako igra često kasni za 500 ms, jednostavno se ne može igrati. Naš cilj je postići iznimno nisku latenciju kako bi jaz između unosa i medija bio što manji. Stoga tradicionalni pristup video streamingu nije primjenjiv ovdje.

Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
Opći predložak igre u oblaku

Projekt otvorenog koda CloudRetro

Odlučio sam napraviti testni uzorak igre u oblaku da vidim je li sve to moguće s tako strogim mrežnim ograničenjima. Odabrao sam Golang za dokaz koncepta jer je to bio jezik koji sam najviše poznavao i bio je vrlo prikladan za ovu implementaciju iz mnogo drugih razloga, kao što sam kasnije otkrio. Go je jednostavan i razvija se vrlo brzo; Kanali u Gou izvrsni su za upravljanje višenitnošću.

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

CloudRetro funkcionalnost

CloudRetro koristi retro igre kako bi demonstrirao moć igranja u oblaku. Što vam omogućuje mnoga jedinstvena iskustva igranja.

  • Prenosivost igre
    • Instant reprodukcija pri otvaranju stranice; nije potrebno preuzimanje niti instalacija
    • Radi u mobilnom pregledniku, tako da za njegovo pokretanje nije potreban softver

  • Sesije igre mogu se dijeliti na više uređaja i pohraniti u oblak za sljedeći put kada se prijavite
  • Igru je moguće streamati ili je može igrati više korisnika odjednom:
    • Crowdplay poput TwitchPlayPokemona, samo više na više platformi i više u stvarnom vremenu
    • Offline igre online. Mnogi korisnici mogu igrati bez postavljanja mreže. Samurai Shodown sada mogu igrati 2 igrača preko CloudRetro mreže

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

    Infrastruktura

    Zahtjevi i tehnološki skup

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

    1. Jedan igrač
    Ovaj se zahtjev ovdje možda ne čini previše važnim ili očiglednim, ali jedan je od mojih ključnih zaključaka, omogućuje igranju u oblaku da bude što dalje od tradicionalnih usluga strujanja. Ako se fokusiramo na igru ​​za jednog igrača, možemo se riješiti centraliziranog poslužitelja ili CDN-a jer ne moramo streamati prema masama. Umjesto učitavanja streamova na ponirući poslužitelj ili prosljeđivanja paketa centraliziranom WebSocket poslužitelju, streamovi usluga isporučuju se izravno korisniku putem peer-to-peer WebRTC veze.

    2. Medijski tok niske latencije
    Čitajući o Stadiji, često vidim spominjanje WebRTC-a u nekim člancima. Shvatio sam da je WebRTC izvanredna tehnologija i savršena za korištenje u igranju u oblaku. WebRTC je projekt koji omogućuje web preglednicima i mobilnim aplikacijama komunikaciju u stvarnom vremenu putem jednostavnog API-ja. Omogućuje peer-to-peer povezivanje, optimiziran je za medije i ima ugrađene standardne kodeke kao što su VP8 i H264.

    Dao sam prednost osiguravanju najboljeg mogućeg korisničkog iskustva u odnosu na održavanje visoke kvalitete grafike. Neki gubici su prihvatljivi u algoritmu. Google Stadia ima dodatni korak smanjenja veličine slike na poslužitelju, a okviri se povećavaju na višu kvalitetu prije nego što se prenesu na iste.

    3. Distribuirana infrastruktura s 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 pridonosi kašnjenju. Arhitektura mora imati mehanizam za uparivanje poslužitelja koji je najbliži korisniku kako bi se smanjilo vrijeme povratnog putovanja (RTT). Arhitektura mora imati 1 koordinatora i nekoliko streaming poslužitelja raspoređenih po cijelom svijetu: zapad SAD-a, istok SAD-a, Europa, Singapur, Kina. Svi streaming poslužitelji moraju biti potpuno izolirani. Sustav može prilagoditi svoju distribuciju kada se poslužitelj pridruži ili napusti mrežu. Stoga, uz veliki promet, dodavanje dodatnih poslužitelja omogućuje horizontalno skaliranje.

    4. Kompatibilnost preglednika
    Igranje u oblaku je najbolje kada od korisnika zahtijeva najmanje. To znači da je moguće pokrenuti u pregledniku. Preglednici pomažu da iskustvo igranja bude što ugodnije za korisnike, štedeći ih od instaliranja softvera i hardvera. Preglednici također pomažu u pružanju funkcionalnosti između mobilnih i stolnih računala. Srećom, WebRTC je dobro podržan u raznim preglednicima.

    5. Jasno odvajanje sučelja igre i usluge
    Na uslugu igranja u oblaku gledam kao na platformu. Svatko bi trebao moći povezati bilo što s platformom. Sad sam se integrirao LibRetro s uslugom igranja u oblaku jer LibRetro nudi prekrasno sučelje emulatora igara za retro igre kao što su SNES, GBA, PS.

    6. Prostorije za multiplayer, crowd play i vanjsko povezivanje (deep-link) s igrom
    CloudRetro podržava mnoge nove gameplaye kao što su CrowdPlay i Online MultiPlayer za retro igre. Ako nekoliko korisnika otvori istu duboku vezu na različitim računalima, vidjet će istu pokrenutu igru ​​i čak će joj se moći pridružiti.

    Štoviše, stanja igre pohranjuju se u pohranu u oblaku. Ovo omogućuje korisnicima da nastave igrati 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 omogućuje vam dodavanje više radnika za opsluživanje većeg prometa.

    8. Nema veze s jednim oblakom
    CloudRetro infrastruktura smještena je na različitim pružateljima usluga oblaka (Digital Ocean, Alibaba, prilagođeni pružatelj) za različite regije. Omogućujem rad u Docker spremniku za infrastrukturu i konfiguriram mrežne postavke pomoću bash skripte kako bih izbjegao zaključavanje u jednog pružatelja usluga oblaka. Kombinacijom ovoga s NAT Traversal-om u WebRTC-u, možemo imati fleksibilnost za implementaciju CloudRetro-a na bilo kojoj platformi u oblaku, pa čak i na bilo kojem korisničkom računalu.

    Arhitektonski dizajn

    Radnik: (ili gore spomenuti poslužitelj za strujanje) umnožava igre, pokreće cjevovod za kodiranje i struji kodirane medije korisnicima. Worker instance su raspoređene po cijelom svijetu, a svaki radnik može upravljati s više korisničkih sesija istovremeno.

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

    Pohrana stanja igre: središnja udaljena pohrana za sva stanja igre. Ova pohrana pruža važne funkcije kao što je daljinsko spremanje/učitavanje.

    Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
    Vrhunska arhitektura CloudRetro-a

    Prilagođena skripta

    Kada novi korisnik otvori CloudRetro u koracima 1 i 2 prikazanim na slici ispod, koordinator zajedno s popisom dostupnih radnika traži se na prvoj stranici. Nakon toga, u koraku 3 klijent izračunava kašnjenja za sve kandidate koristeći HTTP ping zahtjev. Taj se popis kašnjenja zatim šalje natrag koordinatoru kako bi on mogao odrediti najprikladnijeg radnika za posluživanje korisnika. Korak 4 u nastavku stvara igru. Između korisnika i dodijeljenog radnika uspostavlja se WebRTC streaming veza.
    Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
    Korisnička skripta nakon dobivanja pristupa

    Što je unutar radnika

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

    Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
    Međudjelovanje komponenti radnika

    Glavne komponente:

    • WebRTC: klijentska komponenta koja prihvaća korisnički unos i šalje kodirane medije s poslužitelja.
    • Emulator igre: komponenta igre. Zahvaljujući biblioteci Libretro, sustav može pokrenuti igru ​​unutar istog procesa i interno presresti medije i ulazni tok.
    • Okviri u igri se snimaju i šalju koderu.
    • Enkoder slike/audija: cjevovod za kodiranje koji uzima medijske okvire, kodira ih u pozadini i šalje kodirane slike/zvuk.

    Provedba

    CloudRetro se oslanja na WebRTC kao svoju temeljnu tehnologiju, pa sam prije nego što uđem u detalje implementacije Golanga, odlučio govoriti o samom WebRTC-u. Ovo je nevjerojatna tehnologija koja mi je uvelike pomogla u postizanju latencije ispod sekunde za strujanje podataka.

    WebRTC

    WebRTC je dizajniran za pružanje visokokvalitetnih peer-to-peer veza na izvornim mobilnim aplikacijama i preglednicima pomoću jednostavnih API-ja.

    NAT prolaz

    WebRTC je poznat po svojoj funkciji NAT Traversal. WebRTC je dizajniran za peer-to-peer komunikaciju. Cilj mu je pronaći najprikladniju izravnu rutu, izbjegavajući NAT pristupnike i vatrozide za peer-to-peer komunikaciju kroz proces tzv. ICE. Kao dio ovog procesa, WebRTC API-ji pronalaze vašu javnu IP adresu pomoću STUN poslužitelja i prosljeđuju je relejnom poslužitelju (SKRETANJE) kada se ne može uspostaviti izravna veza.

    Međutim, CloudRetro ne iskorištava ovu značajku u potpunosti. Njegove peer-to-peer veze ne postoje između korisnika, već između korisnika i poslužitelja u oblaku. Poslužiteljska strana modela ima manje izravnih komunikacijskih ograničenja od tipičnog korisničkog uređaja. To vam omogućuje da unaprijed otvorite dolazne portove ili izravno koristite javne IP adrese, budući da poslužitelj ne stoji iza NAT-a.

    Prethodno sam projekt želio pretvoriti u platformu za distribuciju igara za Cloud Gaming. Ideja je bila omogućiti kreatorima igara da pružaju igre i resurse za strujanje. Korisnici bi izravno komunicirali s pružateljima usluga. Na ovaj decentralizirani način, CloudRetro je samo okvir za povezivanje resursa strujanja trećih strana s korisnicima, što ga čini skalabilnijim kada se više ne hostira. Uloga WebRTC NAT Traversal ovdje je vrlo važna za olakšavanje inicijalizacije peer-to-peer veze na resursima za strujanje treće strane, olakšavajući kreatoru povezivanje s mrežom.

    Video kompresija

    Kompresija videa neizostavan je dio cjevovoda i uvelike doprinosi glatkom protoku. Iako nije nužno znati svaki detalj VP8/H264 video kodiranja, razumijevanje koncepata može vam pomoći da razumijete opcije brzine strujanja videa, otklonite pogreške neočekivanog ponašanja i prilagodite latenciju.

    Sažimanje videa za uslugu strujanja izazovno je jer algoritam mora osigurati da ukupno vrijeme kodiranja + vrijeme mrežnog prijenosa + vrijeme dekodiranja bude što niže moguće. Osim toga, proces kodiranja mora biti dosljedan i kontinuiran. Neki kompromisi kod kodiranja se ne primjenjuju—na primjer, ne možemo dati prednost dugom vremenu kodiranja u odnosu na manje veličine datoteka i vremena dekodiranja ili koristiti nekonzistentnu kompresiju.

    Ideja video kompresije je eliminirati nepotrebne dijelove informacija uz održavanje prihvatljive razine točnosti za korisnike. Osim kodiranja pojedinačnih okvira statične slike, algoritam zaključuje trenutni okvir iz prethodnog i sljedećeg, tako da se šalje samo njihova razlika. Kao što se može vidjeti iz primjera s Pacmanom, prenose se samo diferencijalne točke.

    Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
    Usporedba video okvira na primjeru Pacmana

    Audio kompresija

    Isto tako, algoritam kompresije zvuka izostavlja podatke koje ljudi ne mogu percipirati. Opus je trenutno najučinkovitiji audio kodek. Dizajniran je za prijenos audio vala putem protokola uređenog datagrama kao što je RTP (Real Time Transport Protocol). Latencija mu je niža od mp3 i aac, a kvaliteta je viša. Latencija je obično oko 5~66,5 ms.

    Pion, WebRTC u Golangu

    Založiti je projekt otvorenog koda koji donosi WebRTC u Golang. Umjesto uobičajenog omota izvornih C++ WebRTC biblioteka, Pion je izvorna Golang implementacija WebRTC-a s boljom izvedbom, Go integracijom i kontrolom verzija na WebRTC protokolima.

    Knjižnica također omogućuje strujanje s puno izvrsnih ugrađenih sadržaja s kašnjenjem od manje od sekunde. Ima vlastitu implementaciju STUN-a, DTLS-a, SCTP-a itd. i neke eksperimente s QUIC-om i WebAssemblyjem. Sama ova knjižnica otvorenog izvornog koda stvarno je dobar resurs za učenje s izvrsnom dokumentacijom, implementacijama mrežnih protokola i cool primjerima.

    Zajednica Pion, koju vodi vrlo strastven kreator, prilično je živa, s puno kvalitetnih rasprava o WebRTC-u. Ako ste zainteresirani za ovu tehnologiju, pridružite se http://pion.ly/slack – naučit ćete puno novih stvari.

    Pisanje CloudRetro-a u Golangu

    Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
    Implementacija worker-a u Go

    Go Channels in Action

    Zahvaljujući prekrasnom dizajnu kanala Go, problemi strujanja događaja i istovremenosti uvelike su pojednostavljeni. Kao na dijagramu, različite GoRoutine imaju više komponenti koje rade paralelno. Svaka komponenta upravlja svojim stanjem i komunicira putem kanala. Golangova selektivna tvrdnja prisiljava da se svaki put u igri obradi jedan atomski događaj (takt igre). To znači da za ovaj dizajn nije potrebno zaključavanje. Na primjer, kada korisnik sprema, potrebna je potpuna snimka stanja igre. Ovo stanje treba ostati kontinuirano, prijavljivanje dok se spremanje ne završi. Tijekom svake igre, pozadina može rukovati samo operacijom spremanja ili unosa, čineći nit procesa sigurnom.

    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

    Ovaj predložak Golang savršeno odgovara mom slučaju korištenja CrowdPlaya i više igrača. Slijedeći ovaj obrazac, svi korisnički ulazi u jednoj prostoriji ugrađeni su u središnji ulazni kanal. Mediji igre zatim se raspoređuju na sve korisnike u istoj prostoriji. Na taj način postižemo podjelu stanja igre između nekoliko sesija igre različitih korisnika.

    Igranje u oblaku otvorenog koda na WebRTC-u: p2p, više igrača, nulta latencija
    Sinkronizacija između različitih sesija

    Nedostaci Golanga

    Golang nije savršen. Kanal je spor. U usporedbi s blokiranjem, Go kanal jednostavno je lakši način za rukovanje istodobnim i nizanim događajima, ali kanal ne pruža najbolju izvedbu. Ispod kanala postoji složena logika blokiranja. Stoga sam napravio neke prilagodbe u implementaciji, ponovno primijenivši zaključavanja i atomske vrijednosti prilikom zamjene kanala kako bih optimizirao izvedbu.

    Osim toga, sakupljačem smeća u Golangu se ne upravlja, što ponekad uzrokuje sumnjivo duge pauze. To uvelike ometa aplikaciju za strujanje u stvarnom vremenu.

    COG

    Projekt koristi postojeću biblioteku otvorenog koda Golang VP8/H264 za kompresiju medija i Libretro za emulatore igara. Sve ove biblioteke jednostavno su omoti C biblioteke u Gou COG. Neki od nedostataka navedeni su u ovaj post Davea Cheneya. Problemi na koje sam naišao:

    • nemogućnost hvatanja pada u CGO, čak i s Golang RecoveryCrash;
    • neuspjeh u identificiranju uskih grla u izvedbi kada nismo u mogućnosti otkriti detaljne probleme u CGO-u.

    Zaključak

    Postigao sam svoj cilj da razumijem usluge igranja u oblaku i stvorim platformu koja mi pomaže da igram nostalgične retro igre sa svojim prijateljima na mreži. Ovaj projekt ne bi bio moguć bez knjižnice Pion i podrške zajednice Pion. 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 istog tjedna, iako nisam imao nikakvog prethodnog znanja o peer-to-peer (P2P) komunikaciji.

    Unatoč jednostavnosti integracije, P2P streaming je doista vrlo složeno područje u računalnoj znanosti. Ona se mora nositi sa složenošću dugotrajne mrežne arhitekture kao što su IP i NAT kako bi stvorila sesiju ravnopravnih korisnika. Tijekom rada na ovom projektu stekao sam mnogo dragocjenog znanja o umrežavanju i optimizaciji performansi, stoga potičem sve da pokušaju izgraditi P2P proizvode koristeći WebRTC.

    CloudRetro zadovoljava sve slučajeve upotrebe koje sam očekivao iz moje perspektive retro igrača. Međutim, mislim da postoje mnoga područja u projektu koja 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 Pratite projekt i podržite ga ako vam se sviđa.

Izvor: www.habr.com

Dodajte komentar