Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.

Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
Som software som service, infrastruktur som service, platform som service, kommunikationsplatform som service, videokonferencer som service, men hvad med skyspil som service? Der er allerede gjort flere forsøg på at skabe skyspil (Cloud Gaming), såsom Stadia, som blev lanceret af Google for nylig. Stadia er ikke en nybegynder inden for WebRTC, men kan andre bruge WebRTC på samme måde?

Thanh Nguyen besluttede at teste denne mulighed i sit open source-projekt CloudRetro. CloudRetro er bygget på Pion, et populært WebRTC-bibliotek baseret på Go (tak til Shawn fra Pion-udviklerteamet for hjælpen til at forberede denne artikel). I denne artikel giver Thanh et overblik over arkitekturen af sit projekt samt hvad nyttigt han har lært og hvilke udfordringer han stødte på under arbejdet.

Introduktion

Sidste år, da Google annoncerede Stadia, blev jeg helt buzzet. Ideen er så unik og innovativ, at jeg konstant spurgte mig selv, hvordan det overhovedet var muligt med de eksisterende teknologier. Ønsket om at forstå emnet bedre fik mig til at skabe min version af et open source-skyspil. Resultatet var ganske fantastisk. Nedenfor vil jeg gerne dele processen med at arbejde på mit årlige projekt.

TLDR: en kort slides-version med hovedpunkterne

Hvorfor skyspil er fremtiden

Jeg tror, at Cloud Gaming snart bliver den nye generation ikke kun af spil, men også af andre områder inden for datalogi. Skyspil er toppen af klient/server-modellen. Denne model maksimerer backend-kontrol og minimerer frontend-arbejde ved at placere spil-logikken på en fjernserver og streame billeder/lyd til klienten. Serveren udfører den tunge behandling, så klienten ikke længere er afhængig af hardwarebegrænsninger.

Google Stadia giver i bund og grund mulighed for at spille AAA-spil (dvs. high-end blockbuster-spil) på en grænseflade som YouTube. Den samme metode kan anvendes på andre krævende offline-applikationer, såsom operativsystemer eller 2D/3D grafisk design, så vi kan køre dem stabilt på enheder med lave specifikationer på tværs af forskellige platforme.

Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
Fremtiden for denne teknologi: forestil dig, hvis Microsoft Windows 10 fungerede i Chrome-browseren?

Skyspil er teknisk komplekse

Gaming er et af de sjældne områder, hvor brugeren kræver en konstant hurtig reaktion. Hvis vi lejlighedsvis oplever en forsinkelse på 2 sekunder ved et klik på siden, er det acceptabelt. Videostrømme i realtid har som regel et efterslæb på flere sekunder, men tilbyder stadig en tilstrækkelig brugervenlighed. Men hvis et spil ofte har en forsinkelse på 500 ms, er det simpelthen umuligt at spille. Vores mål er at opnå en ekstremt lav forsinkelse, så kløften mellem input og medier er så lille som muligt. Derfor er den traditionelle tilgang til streamingvideo ikke anvendelig her.

Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
Generelt skabelon for cloud gaming

Open source-projektet CloudRetro

Jeg besluttede at skabe et testeksempel på cloud gaming for at undersøge, om dette overhovedet er muligt under sådanne strenge netværksbetingelser. Til konceptets validering valgte jeg Golang, da det er det sprog, jeg kender bedst, og som viste sig at være velegnet til denne implementering af mange andre grunde. Go er enkelt og udvikler sig meget hurtigt; Go-kanaler er fremragende til at håndtere multitrådning.

Projekt CloudRetro.io – en cloud gaming service med open source for retro-spil. Projektets mål er at bringe de mest behagelige spilleoplevelser til traditionelle retro-spil og tilføje multiplayer.
Du kan få en detaljeret indsigt i projektet her: https://github.com/giongto35/cloud-game.

CloudRetro-funktionalitet

For at demonstrere kraften af cloud gaming anvendes retro-spil i CloudRetro. Dette giver mulighed for at opnå mange unikke spilleoplevelser.

  • Portabilitet af spil
    • Sofortspil ved åbning af siden; download og installation er ikke nødvendige
    • Fungerer i mobilbrowseren, så ingen softwareinstallation er nødvendig for at starte

  • Spilsessioner kan deles på flere enheder og gemmes i skyen til næste indlogning
  • Spillet kan streames, eller det kan spilles af flere brugere samtidigt:
    • Crowdplay som TwitchPlayPokemon, blot mere tværplatforms og mere realtid
    • Offline spil online. Mange brugere kan spille uden netværksindstillinger. I Samurai Shodown kan nu 2 spillere spille via CloudRetro-netværket

    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Demo-version af multiplayer online-spillet på tværs af enheder

    Infrastruktur

    Krav og teknologistack

    Nedenfor er en liste over kravene, jeg opstillede, inden jeg begyndte på projektet.

    1. En spiller
    Dette krav kan synes ubetydeligt og åbenlyst her, men det er en af mine vigtigste konklusioner; det gør det muligt for cloud gaming at holde sig så langt væk fra traditionelle streamingtjenester som muligt. Hvis vi fokuserer på enspiller-spil, kan vi undgå et centraliseret server eller CDN, fordi vi ikke behøver at streame til masserne. I stedet for at uploade streams til en omfavnende server eller sende pakker til en centraliseret WebSocket-server, leveres service streams direkte til brugeren gennem en peer-to-peer WebRTC-forbindelse.

    2. Lav-latens mediestrøm
    Når jeg læser om Stadia, støder jeg ofte på omtale af WebRTC i nogle artikler. Jeg har indset, at WebRTC er en bemærkelsesværdig teknologi, og det passer perfekt til at blive brugt i cloud gaming. WebRTC er et projekt, der giver web-browsere og mobile applikationer realtidskommunikation gennem et enkelt API. Det tilbyder en peer-to-peer forbindelse, optimeret til medier og har indbyggede standardkodecs som VP8 og H264.

    Jeg har prioriteret at sikre en så komfortabel brugeroplevelse som muligt frem for at bevare høj billedkvalitet. Der er acceptable tab i algoritmen. Google Stadia har et ekstra trin til at reducere billedstørrelsen på serveren, og billederne skaleres til en højere kvalitet før de sendes til peer-noder.

    3. Fordelt infrastruktur med geografisk routing
    Uanset hvor optimal kompressionsalgoritmen og koden er, er netværket stadig en afgørende faktor, der bidrager mest til latens. Arkitekturen skal have en mekanisme til at forbinde til den nærmeste server til brugeren for at reducere round-trip-tiden (RTT). Arkitekturen skal have én koordinator og flere streaming-servere distribueret globalt: Vestlige USA, Østlige USA, Europa, Singapore, Kina. Alle streaming-servere skal være helt isolerede. Systemet kan justere sin distribution, når en server tilsluttes eller frakobles netværket. Således gør tilføjelsen af yderligere servere ved høj trafik mulighed for horisontal skalering.

    4. Browserkompatibilitet
    Cloud gaming shines brightest when it demands minimal from users. This means that there's an opportunity to launch directly in the browser. Browsers help create a comfortable gaming experience for users, freeing them from the need to install software and hardware. Browsers also support cross-platform compatibility for both mobile and desktop versions. Fortunately, WebRTC is well-supported across various browsers.

    5. Klart adskilt mellem gaming interface og service
    Jeg betragter cloud gaming service som en platform. Alle skal have mulighed for at forbinde hvad som helst til platformen. Jeg har nu integreret LibRetro med cloud gaming servizio, fordi LibRetro tilbyder et flot interface til en spille emulator for retro-spil som SNES, GBA, PS.

    6. Værelser til multiplayer, crowd play og deep-linking med spillet
    CloudRetro understøtter mange nye gameplay-funktioner, såsom CrowdPlay og Online MultiPlayer til retro-spil. Hvis flere brugere åbner det samme deep-link på forskellige computere, vil de se det samme kørende spil og endda kunne deltage i det.

    Desuden gemmes spiltilstande i det cloud-baserede lager. Dette giver brugerne mulighed for at fortsætte spillet når som helst på enhver anden enhed.

    7. Horisontal skalering
    Som enhver SaaS-løsning i dag, skal cloud gaming designes til at være horisontalt skalerbar. Arkitekturen 'koordinator-arbejder' giver mulighed for at tilføje flere arbejdere for at håndtere større trafik.

    8. Ingen binding til et enkelt cloud
    CloudRetro's infrastruktur hostes på forskellige cloud-udbydere (Digital Ocean, Alibaba, brugerdefineret udbyder) for forskellige regioner. Jeg aktiverer lanceringen i Docker-containere for infrastrukturen og konfigurerer netværksindstillingerne med en bash-script for at undgå afhængighed af en enkelt cloud-udbyder. Ved at kombinere dette med NAT Traversal i WebRTC kan vi opnå fleksibilitet til at implementere CloudRetro på enhver cloud-platform og endda på maskiner fra enhver bruger.

    Arkitektonisk design

    Arbejder: (eller den streamende server, nævnt ovenfor) multiplicerer spil, starter en kodningspipeline og sender det kodede media til brugerne. Arbejdsinstanser er distribueret globalt, og hver arbejder kan håndtere flere brugersessioner samtidigt.

    Koordinator: ansvarlig for at tilslutte en ny bruger til den mest passende arbejder for streaming. Koordinatoren interagerer med arbejderne via WebSocket.

    Lager af spiltilstande: et centralt fjerntilgangslager for alle spiltilstande. Dette lager sikrer vigtige funktioner såsom fjerntilgang til gemte/spillede tilstande.

    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Overordnet arkitektur for CloudRetro

    Brugsscenario

    Når en ny bruger åbner CloudRetro i trin 1 og 2, som vist nedenfor, anmodes koordinatoren sammen med en liste over tilgængelige arbejdere på den første side. Derefter beregner klienten i trin 3 latenserne for alle kandidater ved hjælp af en HTTP ping-anmodning. Denne liste over latenser sendes tilbage til koordinatoren, så han kan bestemme den mest passende arbejder til at betjene brugeren. I trin 4 nedenfor oprettes spillet. Et streaming WebRTC-forbindelse etableres mellem brugeren og den tildelte arbejder.
    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Brugsscenario efter adgang

    Hvad er inde i arbejderens komponent?

    Spil- og streamingpipelines opbevares isoleret indeni arbejdere og udveksler information gennem et interface. I øjeblikket sker denne forbindelse via datatransmission i hukommelsen via Golang-kanaler i den samme proces. Det næste mål er segmentering, dvs. uafhængig kørsel af spillet i en anden proces.

    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Interaktion mellem arbejds-komponenter

    De vigtigste komponenter:

    • WebRTC: klientkomponenten, der modtager brugerinput og outputter det kodede media fra serveren.
    • Spil emulator: spilkoden. Takket være Libretro-biblioteket kan systemet køre spillet inden for samme proces og internt opfange media og inputstrøm.
    • Spillens interne frames opfanges og sendes til koderen.
    • Billede-/lydkoder: kodningspipeline, der modtager mediac frames, koder dem i baggrunden og sender de kodede billeder/lyd.

    Implementering

    CloudRetro bygger på WebRTC som dens grundlæggende teknologi, så før jeg dykker ned i detaljerne omkring implementeringen i Golang, vil jeg fortælle om WebRTC selv. Det er en fantastisk teknologi, der har hjulpet mig med at opnå en forsinkelse i datastreaming på kun en brøkdel af et sekund.

    WebRTC

    WebRTC er designet til at sikre høj-kvalitets peer-to-peer forbindelser på native mobilapplikationer og i browsere gennem enkle API'er.

    NAT Traversal

    WebRTC er kendt for sin NAT Traversal funktionalitet. WebRTC er designet til peer-to-peer kommunikation. Dets mål er at finde den mest passende direkte rute, der undgår NAT-gateways og firewalls for peer-to-peer kommunikation gennem en proces kaldet ICE. I denne proces finder WebRTC API'en din offentlige IP-adresse ved hjælp af STUN-servere og videresender den til en relay-server (TURN), når en direkte forbindelse ikke kan etableres.

    CloudRetro udnytter dog ikke denne mulighed fuldt ud. Dets peer-to-peer forbindelser findes ikke mellem brugere, men mellem brugere og cloud-servere. Serverdelen af modellen har færre begrænsninger for direkte forbindelser end en typisk brugerenhed. Dette muliggør på forhånd at åbne indgående porte eller bruge offentlige IP-adresser direkte, da serveren ikke er bag NAT.

    Tidligere ønskede jeg at omdanne projektet til en distribueringsplatform for spil til Cloud Gaming. Ideen var at lade spiludviklere tilbyde deres spil og streamingsressourcer. Og brugerne ville interagere direkte med udbyderne. På en sådan decentraliseret måde er CloudRetro kun et middel til at forbinde tredjeparts streamingsressourcer med brugerne, hvilket gør det mere skalerbart, når det ikke længere har hosting. Rollen af WebRTC NAT Traversal er her meget vigtig for at lette initialiseringen af peer-to-peer forbindelsen til tredjeparts streamingsressourcer, hvilket gør det lettere for udvikleren at forbinde til netværket.

    Video komprimering

    Videokompression er en uundgåelig del af pipeline, som i høj grad bidrager til flowets glathed. Selvom det ikke er nødvendigt at kende alle detaljer om videokodning i VP8/H264, hjælper forståelsen af konceptet med at håndtere parametrene for streaminghastighed, fejlfinde uventet adfærd og justere forsinkelse.

    Videokompression til streamingtjenester er en kompleks opgave, da algoritmen skal sikre, at den samlede kodningstid + netværksoverførselstid + dekodningstid er så lav som muligt. Derudover skal kodningsprocessen være konsistent og kontinuerlig. Nogle indbyrdes kompromiser ved kodning er ikke anvendelige – for eksempel kan vi ikke prioritere længere kodningstid over mindre filstørrelse og dekodningstid eller anvende inkonsistent kompression.

    Ideen med videokompression er at udelade unødvendige bits af information, samtidig med at et acceptabelt niveau af nøjagtighed for brugerne opretholdes. Ud over at kode individuelle statiske billedrammer laver algoritmen en antagelse for det aktuelle billede baseret på det foregående og det næste, så kun forskellen mellem dem sendes. Som det ses i eksemplet med Pacman, sendes kun de differentielle punkter.

    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Sammenligning af videorammer med Pacman-eksemplet

    Kompresion af lyd

    På samme måde udelader lyddatakompresseringsalgoritmen data, der ikke kan opfattes af mennesker. Opus er i øjeblikket den lydkodek med den bedste ydelse. Den er udviklet til at transmittere lydsignaler via protokoller til ordnet datagram, såsom RTP (Real Time Transport Protocol – protokol til transmission af realtids trafik). Dens latens er lavere end mp3 og aac, og kvaliteten er højere. Latensen ligger normalt omkring 5~66,5 ms.

    Pion, WebRTC i Golang

    Pion – er et open source-projekt, der bringer WebRTC til Golang. I stedet for den sædvanlige indpakning af native C++ WebRTC-biblioteker er Pion en native Golang-implementering af WebRTC med bedre ydeevne, integration med Go samt versionskontrol på WebRTC-protokoller.

    Biblioteket tilbyder også streaming med mange fremragende indbyggede moduler med mindre end et sekunds forsinkelse. Det har sin egen implementering af STUN, DTLS, SCTP osv. og nogle eksperimenter med QUIC og WebAssembly. Selve denne open source-bibliotek er en virkelig god læringskilde med fremragende dokumentation, implementering af netværksprotokoller og flotte eksempler.

    Pion-fællesskabet, ledet af en meget passioneret skaber, er ret livligt, der er mange kvalitetsdiskussioner om WebRTC. Hvis du er interesseret i denne teknologi, så tilslut dig http://pion.ly/slack – du vil lære meget nyt.

    Skrivning af CloudRetro i Golang

    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Implementering af en worker i Go

    Go-kanaler i aktion

    Takket være det smukke design af Go-kanaler bliver problemer med begivenhedsstreaming og parallelisme betydeligt forenklet. Som vist i diagrammet, arbejder flere komponenter parallelt i forskellige GoRoutines. Hver komponent styrer sin egen tilstand og kommunikerer via kanaler. Den selektive udsagn i Golang tvinger os til at behandle ét atomar begivenhed ad gangen i hvert øjeblik i spillet (game tick). Det betyder, at der ikke er behov for låsning i et sådant design. For eksempel, når en bruger gemmer, kræves et fuldt snapshot af spillets tilstand. Denne tilstand skal forblive kontinuerlig, mens den logger ind, indtil gemmingen er fuldført. Under hvert game tick kan backend kun håndtere enten gemme- eller inputoperationen, hvilket gør processen trådsikker.

    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

    Denne Golang-skabelon passer perfekt til mit brugsscenarie med CrowdPlay og Multiple Player. Ved at følge denne skabelon integreres alle brugerindgange i et enkelt rum i en central indgangskanal. Spilmedierne distribueres derefter til alle brugere i det samme rum. På denne måde opnår vi en opdeling af spillets tilstand mellem flere spilsessioner fra forskellige brugere.

    Cloud gaming med åbne kilder på WebRTC: p2p, multiplayer, zero latency.
    Synkronisering mellem forskellige sessioner

    Ulemper ved Golang

    Golang er ikke perfekt. Kanalen er langsom. I forhold til kan blokkering af Go – det er blot en enklere måde at håndtere parallelle og strømlinede hændelser på, men kanalen giver ikke den bedste ydeevne. Under kanalen findes der kompleks blokkeringslogik. Derfor har jeg lavet nogle justeringer i implementeringen ved at genanvende blokeringer og atomare værdier, når jeg erstatter kanaler for at optimere ydeevnen.

    Desuden er garbage collector i Golang ukontrolleret, hvilket nogle gange fører til mistænkeligt lange pauser. Dette er en stor hindring for realtidsapplikationer.

    CGO

    Projektet bruger den eksisterende VP8/H264 Golang open source-bibliotek til mediekomprimering og Libretro til spille-emulatorer. Alle disse biblioteker er blot indpakninger af C-biblioteket i Go ved at bruge CGO. Nogle af manglerne er nævnt i denne post af Dave Cheney. Problemerne, jeg har stødt på:

    • umuligheden af at fange crashes i CGO, selv med Golang RecoveryCrash;
    • umuligheden af at identificere flaskehalse i ydeevnen, når vi ikke kan opdage detaljerede problemer i CGO.

    Konklusion

    Jeg nåede mit mål – at forstå cloud gaming-tjenester og skabe en platform, der gør det muligt at spille nostalgiske retro-spil med mine venner online. Oprettelsen af dette projekt ville ikke have været muligt uden Pion-biblioteket og Pion-fællesskabets støtte. Jeg er ekstremt taknemmelig for den intensive udvikling. De enkle API'er, der tilbydes af WebRTC og Pion, sikrede en glidende integration. Mit første proof of concept blev frigivet i den samme uge, selvom jeg ikke på forhånd kendte til peer-to-peer-forbindelse (P2P).

    På trods af den enkle integration er P2P-streaming faktisk et meget komplekst område inden for computervidenskab. Det må håndtere kompleksiteten af mangeårige netværksarkitekturer som IP og NAT for at etablere en peer-to-peer-session. I løbet af mit arbejde med dette projekt har jeg opsamlet mange værdifulde indsigter om netværk og performanceoptimering, så jeg anbefaler alle at prøve at bygge P2P-produkter ved hjælp af WebRTC.

    CloudRetro dækker alle brugsscenarier, som jeg forventede, set fra mit perspektiv som retro-gamer. Jeg mener dog, at der er mange områder i projektet, jeg kan forbedre, såsom at gøre netværket mere pålideligt og effektivt, sikre en bedre grafisk kvalitet i spillene, eller muligheden for at dele spil mellem brugere. Jeg arbejder hårdt på dette. Følg venligst med projekt og støt det, hvis du kan lide det.

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster