Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero

Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
Software ca serviciu, infrastructură ca serviciu, platformă ca serviciu, platformă de comunicare ca serviciu, videoconferință ca serviciu, cum rămâne cu jocurile în cloud ca serviciu? Au existat deja mai multe încercări de a crea jocuri în cloud (Cloud Gaming), precum Stadia, lansat recent de Google. Stadia nu este nou pentru WebRTC, dar alții pot folosi WebRTC în același mod?

Thanh Nguyen a decis să testeze această oportunitate în proiectul său open source CloudRetro. CloudRetro se bazează pe Pion, popular Biblioteca WebRTC bazată pe Go (mulțumesc Afișate din partea echipei de dezvoltare Pion pentru sprijinul acordat în pregătirea acestui articol). În acest articol, Thanh oferă o privire de ansamblu asupra arhitecturii proiectului său și, de asemenea, vorbește despre ce lucruri utile a învățat și ce provocări a întâlnit în timpul muncii sale.

Intrare

Anul trecut, când Google a anunțat Stadia, m-a uimit. Ideea este atât de unică și inovatoare încât m-am întrebat constant cum a fost posibil acest lucru chiar și cu tehnologia existentă. Dorința de a înțelege mai bine acest subiect m-a determinat să îmi creez propria versiune a unui joc cloud open-source. Rezultatul a fost pur și simplu fantastic. Mai jos aș dori să împărtășesc procesul de lucru în anul meu proiect.

TLDR: versiune scurtă de diapozitive cu evidențieri

De ce jocurile în cloud sunt viitorul

Cred că Cloud Gaming va deveni în curând următoarea generație nu numai de jocuri, ci și alte domenii ale informaticii. Jocurile în cloud sunt apogeul modelului client/server. Acest model maximizează gestionarea backend-ului și minimizează munca frontală prin găzduirea logicii jocului pe un server la distanță și transmiterea de imagini/audio către client. Serverul face procesarea grea, astfel încât clientul nu mai este la cheremul limitărilor hardware.

Google Stadia vă permite în esență să jucați Jocuri AAA (adică jocuri de succes de ultimă generație) pe o interfață precum YouTube. Aceeași metodologie poate fi aplicată și altor aplicații grele offline, cum ar fi sistemul de operare sau designul grafic 2D/3D etc. astfel încât să le putem rula în mod constant pe dispozitive cu specificații reduse pe mai multe platforme.

Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
Viitorul acestei tehnologii: imaginați-vă dacă Microsoft Windows 10 ar rula pe browserul Chrome?

Jocurile în cloud sunt provocatoare din punct de vedere tehnic

Jocurile sunt una dintre acele domenii rare în care este necesar un răspuns constant și rapid al utilizatorului. Dacă ocazional întâlnim o întârziere de 2 secunde când facem clic pe o pagină, acest lucru este acceptabil. Fluxurile video live tind să întârzie câteva secunde, dar oferă totuși o utilizare rezonabilă. Cu toate acestea, dacă jocul întârzie frecvent cu 500 ms, este pur și simplu nejucat. Scopul nostru este să obținem o latență extrem de scăzută, astfel încât decalajul dintre intrare și media să fie cât mai mic posibil. Prin urmare, abordarea tradițională a streamingului video nu este aplicabilă aici.

Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
Șablon de joc general Cloud

Proiect open source CloudRetro

Am decis să creez o probă de testare a unui joc în cloud pentru a vedea dacă toate acestea sunt posibile cu restricții atât de stricte de rețea. Am ales Golang pentru demonstrarea conceptului, deoarece era limbajul cu care eram cel mai familiar și era potrivit pentru această implementare din multe alte motive, așa cum am descoperit mai târziu. Go este simplu și se dezvoltă foarte repede; Canalele din Go sunt excelente pentru gestionarea multithreading-ului.

Proiect CloudRetro.io este un serviciu de jocuri în cloud open source pentru jocuri retro. Scopul proiectului este de a aduce cea mai confortabilă experiență de joc în jocurile retro tradiționale și de a adăuga multiplayer.
Puteți afla mai multe despre proiect aici: https://github.com/giongto35/cloud-game.

Funcționalitatea CloudRetro

CloudRetro folosește jocuri retro pentru a demonstra puterea jocurilor în cloud. Ceea ce vă permite să obțineți multe experiențe unice de joc.

  • Portabilitatea jocului
    • Redare instantanee la deschiderea paginii; nu este nevoie de descărcare sau instalare
    • Funcționează într-un browser mobil, deci nu este nevoie de software pentru a-l rula

  • Sesiunile de joc pot fi partajate pe mai multe dispozitive și stocate în cloud pentru următoarea conectare
  • Jocul poate fi transmis în flux sau poate fi jucat de mai mulți utilizatori simultan:
    • Crowdplay ca TwitchPlayPokemon, doar mai mult multi-platformă și mai mult în timp real
    • Jocuri offline online. Mulți utilizatori se pot juca fără a configura o rețea. Samurai Shodown poate fi jucat acum de 2 jucători prin rețeaua CloudRetro

    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Versiunea demo a jocului multiplayer online pe diferite dispozitive

    Infrastructură

    Cerințe și stiva de tehnologie

    Mai jos este o listă de cerințe pe care le-am stabilit înainte de a începe proiectul.

    1. Un jucător
    Această cerință poate să nu pară prea importantă sau evidentă aici, dar este una dintre concluziile mele cheie, care permite jocurilor în cloud să rămână cât mai departe de serviciile tradiționale de streaming. Dacă ne concentrăm pe un joc single-player, putem scăpa de un server centralizat sau de CDN pentru că nu trebuie să transmitem în flux către mase. În loc să încărcați fluxuri pe un server receptor sau să transmiteți pachete către un server WebSocket centralizat, fluxurile de servicii sunt livrate direct utilizatorului printr-o conexiune WebRTC peer-to-peer.

    2. Flux media cu latență scăzută
    Citind despre Stadia, văd adesea că WebRTC este menționat în unele articole. Mi-am dat seama că WebRTC este o tehnologie remarcabilă și este perfectă pentru utilizarea în jocurile în cloud. WebRTC este un proiect care oferă browserelor web și aplicațiilor mobile comunicare în timp real printr-un API simplu. Oferă conectivitate peer-to-peer, este optimizat pentru media și are codecuri standard încorporate, cum ar fi VP8 și H264.

    Am prioritizat asigurarea celei mai bune experiențe de utilizator posibilă față de menținerea graficii de înaltă calitate. Unele pierderi sunt acceptabile în algoritm. Google Stadia are un pas suplimentar de reducere a dimensiunii imaginii de pe server, iar cadrele sunt mărite la o calitate superioară înainte de a fi transmise colegilor.

    3. Infrastructură distribuită cu rutare geografică
    Indiferent cât de optimizate sunt algoritmul de compresie și codul, rețeaua este în continuare factorul decisiv care contribuie cel mai mult la latență. Arhitectura trebuie să aibă un mecanism de împerechere a serverului cel mai apropiat de utilizator pentru a reduce timpul de călătorie dus-întors (RTT). Arhitectura trebuie să aibă 1 coordonator și mai multe servere de streaming distribuite în întreaga lume: Vestul SUA, Estul SUA, Europa, Singapore, China. Toate serverele de streaming trebuie să fie complet izolate. Sistemul își poate ajusta distribuția atunci când un server se alătură sau părăsește rețeaua. Astfel, cu trafic mare, adăugarea de servere suplimentare permite scalarea orizontală.

    4. Compatibilitate browser
    Jocurile în cloud sunt cele mai bune atunci când necesită cel mai puțin de la utilizatori. Aceasta înseamnă că este posibil să rulați într-un browser. Browserele ajută utilizatorii să facă experiența de joc cât mai confortabilă posibil, scutindu-i de la instalarea de software și hardware. Browserele ajută, de asemenea, să ofere funcționalitate multiplatformă între versiunile mobile și desktop. Din fericire, WebRTC este bine acceptat într-o varietate de browsere.

    5. Separare clară a interfeței jocului și a serviciului
    Văd serviciul de jocuri în cloud ca pe o platformă. Toată lumea ar trebui să poată conecta orice la platformă. Acum m-am integrat LibRetro cu serviciul de jocuri în cloud, deoarece LibRetro oferă o interfață frumoasă de emulator de jocuri pentru jocuri retro precum SNES, GBA, PS.

    6. Camere pentru multiplayer, joc în mulțime și legături externe (deep-link) cu jocul
    CloudRetro acceptă multe jocuri noi, cum ar fi CrowdPlay și Online MultiPlayer pentru jocuri retro. Dacă mai mulți utilizatori deschid aceeași legătură profundă pe computere diferite, ei vor vedea același joc care rulează și chiar se vor putea alătura acestuia.

    Mai mult, stările jocului sunt stocate în stocarea în cloud. Acest lucru permite utilizatorilor să continue să joace în orice moment pe orice alt dispozitiv.

    7. Scalare orizontală
    Ca orice SAAS din zilele noastre, jocurile în cloud trebuie concepute pentru a fi scalabile pe orizontală. Designul coordonator-lucrător vă permite să adăugați mai mulți lucrători pentru a deservi mai mult trafic.

    8. Nicio conexiune la un singur nor
    Infrastructura CloudRetro este găzduită pe diferiți furnizori de cloud (Digital Ocean, Alibaba, furnizor personalizat) pentru diferite regiuni. Activez rularea într-un container Docker pentru infrastructură și configurez setările de rețea folosind un script bash pentru a evita să fiu blocat într-un singur furnizor de cloud. Combinând acest lucru cu NAT Traversal în WebRTC, putem avea flexibilitatea de a implementa CloudRetro pe orice platformă cloud și chiar pe mașinile oricărui utilizator.

    Design arhitectural

    Muncitor: (sau serverul de streaming menționat mai sus) multiplică jocurile, rulează conducta de codare și transmite conținutul media codificat către utilizatori. Instanțele de lucrător sunt distribuite în întreaga lume și fiecare lucrător poate gestiona mai multe sesiuni de utilizator simultan.

    Coordonator: este responsabil pentru împerecherea noului utilizator cu cel mai potrivit lucrător pentru streaming. Coordonatorul interacționează cu lucrătorii prin WebSocket.

    Stocarea stării jocului: stocare centrală la distanță pentru toate stările de joc. Această stocare oferă funcții importante, cum ar fi salvarea/încărcarea de la distanță.

    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Arhitectura de nivel superior a CloudRetro

    Script personalizat

    Când un utilizator nou deschide CloudRetro în pașii 1 și 2 din figura de mai jos, coordonatorul împreună cu lista lucrătorilor disponibili sunt solicitați pe prima pagină. După aceasta, în pasul 3 clientul calculează întârzierile pentru toți candidații folosind o solicitare ping HTTP. Această listă de întârzieri este apoi trimisă înapoi coordonatorului, astfel încât acesta să poată determina cel mai potrivit lucrător care să servească utilizatorul. Pasul 4 de mai jos creează jocul. Se stabilește o conexiune de streaming WebRTC între utilizator și lucrătorul desemnat.
    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Script utilizator după obținerea accesului

    Ce se află în interiorul lucrătorului

    Conductele de jocuri și de streaming sunt stocate în interiorul lucrătorului în mod izolat și fac schimb de informații acolo prin interfață. În prezent, această comunicare se realizează prin transferul de date în memorie prin Canalele Golang in acelasi proces. Următorul obiectiv este segregarea, adică. lansare independentă a jocului într-un alt proces.

    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Interacțiunea componentelor lucrătorului

    Componentele principale:

    • WebRTC: o componentă client care acceptă intrarea utilizatorului și scoate media codificată de pe server.
    • Emulator de joc: componenta de joc. Datorită bibliotecii Libretro, sistemul este capabil să ruleze jocul în cadrul aceluiași proces și să intercepteze intern media și fluxul de intrare.
    • Cadrele din joc sunt capturate și trimise la codificator.
    • Codificator imagine/audio: o conductă de codare care preia cadre media, le codifică în fundal și emite imagini/sunet codificate.

    punerea în aplicare

    CloudRetro se bazează pe WebRTC ca tehnologie de bază, așa că înainte de a mă scufunda în detaliile implementării Golang, am decis să vorbesc despre WebRTC în sine. Aceasta este o tehnologie uimitoare care m-a ajutat foarte mult să obțin o latență de sub secunde pentru transmiterea datelor în flux.

    WebRTC

    WebRTC este conceput pentru a oferi conexiuni peer-to-peer de înaltă calitate pe aplicații și browsere mobile native folosind API-uri simple.

    Traversarea NAT

    WebRTC este cunoscut pentru funcționalitatea sa NAT Traversal. WebRTC este conceput pentru comunicare peer-to-peer. Scopul său este de a găsi cea mai potrivită rută directă, evitând gateway-urile NAT și firewall-urile pentru comunicarea peer-to-peer printr-un proces numit ICE. Ca parte a acestui proces, API-urile WebRTC găsesc adresa IP publică utilizând serverele STUN și o transmit către serverul de retransmisie (ÎNTORCĂ) când nu se poate stabili o conexiune directă.

    Cu toate acestea, CloudRetro nu exploatează pe deplin această caracteristică. Conexiunile sale peer-to-peer nu există între utilizatori, ci între utilizatori și serverele cloud. Partea de server a modelului are mai puține restricții de comunicare directă decât un dispozitiv de utilizator obișnuit. Acest lucru vă permite să deschideți în prealabil porturile de intrare sau să utilizați direct adrese IP publice, deoarece serverul nu este în spatele NAT.

    Anterior, am vrut să transform proiectul într-o platformă de distribuție a jocurilor pentru Cloud Gaming. Ideea a fost să le permită creatorilor de jocuri să ofere jocuri și resurse de streaming. Și utilizatorii ar interacționa direct cu furnizorii. În acest mod descentralizat, CloudRetro este doar un cadru pentru conectarea resurselor de streaming terță parte la utilizatori, făcându-l mai scalabil atunci când nu mai este găzduit. Rolul WebRTC NAT Traversal aici este foarte important pentru a facilita inițializarea conexiunii peer-to-peer pe resursele de streaming terță parte, facilitând conectarea creatorului la rețea.

    Compresie video

    Compresia video este o parte indispensabilă a conductei și contribuie în mare măsură la un flux fluid. Deși nu este necesar să cunoașteți fiecare detaliu al codificării video VP8/H264, înțelegerea conceptelor vă poate ajuta să înțelegeți opțiunile de viteză video în flux, să depanați comportamentul neașteptat și să ajustați latența.

    Comprimarea videoclipurilor pentru un serviciu de streaming este o provocare, deoarece algoritmul trebuie să se asigure că timpul total de codificare + timpul de transmisie prin rețea + timpul de decodare este cât mai mic posibil. În plus, procesul de codificare trebuie să fie consecvent și continuu. Unele compromisuri de codare nu se aplică — de exemplu, nu putem favoriza timpii lungi de codare față de dimensiuni mai mici ale fișierelor și timpii de decodare sau să folosim compresie inconsecventă.

    Ideea din spatele compresiei video este de a elimina fragmentele inutile de informații, menținând în același timp un nivel acceptabil de acuratețe pentru utilizatori. Pe lângă codificarea cadrelor de imagine statice individuale, algoritmul deduce cadrul curent din precedentul și următorul, astfel încât este trimisă doar diferența lor. După cum se poate vedea din exemplul cu Pacman, sunt transmise doar puncte diferențiale.

    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Comparație de cadre video folosind Pacman ca exemplu

    Compresie audio

    De asemenea, algoritmul de compresie audio omite date care nu pot fi percepute de oameni. Opus este în prezent cel mai performant codec audio. Este conceput pentru a transmite o undă audio printr-un protocol de datagramă ordonat, cum ar fi RTP (Protocol de transport în timp real). Latența sa este mai mică decât mp3 și aac, iar calitatea este mai mare. Latența este de obicei în jur de 5 ~ 66,5 ms.

    Pion, WebRTC în Golang

    pion este un proiect open source care aduce WebRTC în Golang. În loc de împachetarea obișnuită a bibliotecilor native C++ WebRTC, Pion este o implementare nativă Golang a WebRTC cu performanțe mai bune, integrare Go și control al versiunilor pe protocoalele WebRTC.

    Biblioteca permite, de asemenea, transmiterea în flux cu o mulțime de încorporate grozave, cu o latență de sub secundă. Are propria sa implementare STUN, DTLS, SCTP etc. și câteva experimente cu QUIC și WebAssembly. Această bibliotecă open source în sine este o resursă de învățare foarte bună, cu documentație excelentă, implementări de protocol de rețea și exemple interesante.

    Comunitatea Pion, condusă de un creator foarte pasionat, este destul de animată, cu o mulțime de discuții de calitate despre WebRTC. Dacă sunteți interesat de această tehnologie, alăturați-vă http://pion.ly/slack – vei învăța o mulțime de lucruri noi.

    Se scrie CloudRetro în Golang

    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Implementarea unui lucrător în Go

    Go Channels in Action

    Datorită designului frumos al canalului Go, problemele de transmitere a evenimentelor și concurența sunt mult simplificate. Ca și în diagramă, diferite GoRoutine au mai multe componente care rulează în paralel. Fiecare componentă își gestionează starea și comunică prin canale. Afirmația selectivă a lui Golang forțează ca un eveniment atomic să fie procesat de fiecare dată în joc (bifarea jocului). Aceasta înseamnă că nu este necesară blocarea pentru acest design. De exemplu, când un utilizator salvează, este necesară o imagine completă a stării jocului. Această stare ar trebui să rămână continuă, conectându-vă până când salvarea este completă. În timpul fiecărei bifări de joc, backend-ul poate gestiona doar o operație de salvare sau introducere, făcând firul de lucru sigur.

    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

    Acest șablon Golang se potrivește perfect cu cazul meu CrowdPlay și Multiple Player. Urmând acest model, toate intrările utilizatorului dintr-o cameră sunt încorporate în canalul de intrare central. Media de joc este apoi implementată tuturor utilizatorilor din aceeași cameră. În acest fel, obținem împărțirea stării jocului între mai multe sesiuni de joc ale diferiților utilizatori.

    Jocuri în cloud open source pe WebRTC: p2p, multiplayer, latență zero
    Sincronizare între diferite sesiuni

    Dezavantajele lui Golang

    Golang nu este perfect. Canalul este lent. În comparație cu blocarea, canalul Go este pur și simplu o modalitate mai ușoară de a gestiona evenimentele concurente și în fire, dar canalul nu oferă cea mai bună performanță. Există o logică de blocare complexă sub canal. Așa că am făcut câteva ajustări la implementare, reaplicând blocări și valori atomice la înlocuirea canalelor pentru a optimiza performanța.

    În plus, gunoiul din Golang este negestionat, ceea ce provoacă uneori pauze suspect de lungi. Acest lucru interferează foarte mult cu aplicația de streaming în timp real.

    COG

    Proiectul folosește biblioteca existentă open source Golang VP8/H264 pentru compresia media și Libretro pentru emulatorii de jocuri. Toate aceste biblioteci sunt pur și simplu pachete ale bibliotecii C din Go using COG. Unele dintre dezavantaje sunt enumerate în această postare de Dave Cheney. Probleme pe care le-am intampinat:

    • incapacitatea de a surprinde un accident în CGO, chiar și cu Golang RecoveryCrash;
    • eșecul de a identifica blocajele de performanță atunci când nu putem detecta probleme detaliate în CGO.

    Concluzie

    Mi-am atins obiectivul de a înțelege serviciile de jocuri în cloud și de a crea o platformă care să mă ajute să joc jocuri retro nostalgice cu prietenii mei online. Acest proiect nu ar fi fost posibil fără biblioteca Pion și sprijinul comunității Pion. Sunt extrem de recunoscător pentru dezvoltarea sa intensivă. API-urile simple furnizate de WebRTC și Pion au asigurat o integrare perfectă. Prima mea dovadă a conceptului a fost lansată în aceeași săptămână, deși nu aveam cunoștințe anterioare despre comunicarea de la egal la egal (P2P).

    În ciuda ușurinței integrării, streamingul P2P este într-adevăr un domeniu foarte complex în informatică. Ea trebuie să facă față complexității arhitecturilor de rețea de lungă durată, cum ar fi IP și NAT, pentru a crea o sesiune peer-to-peer. În timp ce lucram la acest proiect, am dobândit o mulțime de cunoștințe valoroase despre rețele și optimizarea performanței, așa că îi încurajez pe toată lumea să încerce să construiască produse P2P folosind WebRTC.

    CloudRetro se adresează tuturor cazurilor de utilizare la care mă așteptam din perspectiva mea de jucător retro. Cu toate acestea, cred că există multe domenii ale proiectului pe care le pot îmbunătăți, cum ar fi să fac rețeaua mai fiabilă și mai performantă, oferind o grafică de joc de calitate superioară sau abilitatea de a partaja jocuri între utilizatori. Lucrez din greu la asta. Te rog urmareste proiect și susține-l dacă îți place.

Sursa: www.habr.com

Adauga un comentariu