Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés

Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
Szoftver mint szolgáltatás, infrastruktúra mint szolgáltatás, platform mint szolgáltatás, kommunikációs platform mint szolgáltatás, videokonferencia mint szolgáltatás, mi a helyzet a felhőjátékkal mint szolgáltatással? Már több kísérlet is történt felhőjáték (Cloud Gaming) létrehozására, mint például a Google által nemrégiben elindított Stadia. Stadia nem új a WebRTC-ben, de mások is használhatják ugyanígy a WebRTC-t?

Thanh Nguyen úgy döntött, hogy kipróbálja ezt a lehetőséget nyílt forráskódú CloudRetro projektjén. A CloudRetro a Pionon alapul, népszerű Go alapú WebRTC könyvtár (köszönjük Látható a Pion fejlesztőcsapatától a cikk elkészítésében nyújtott segítségükért). Ebben a cikkben Thanh áttekintést ad projektje felépítéséről, és arról is beszél, hogy milyen hasznos dolgokat tanult, és milyen kihívásokkal találkozott munkája során.

Belépés

Tavaly, amikor a Google bejelentette a Stadiát, felrobbant a fejemben. Az ötlet annyira egyedi és innovatív, hogy folyamatosan azon töprengtem, hogyan lehetséges ez a meglévő technológiával. A téma jobb megértésének vágya késztetett arra, hogy elkészítsem egy nyílt forráskódú felhőjáték saját verzióját. Az eredmény egyszerűen fantasztikus volt. Az alábbiakban szeretném megosztani az évemmel való munka folyamatát projekt.

TLDR: rövid diaváltozat kiemelésekkel

Miért a felhőjáték a jövő?

Úgy gondolom, hogy a Cloud Gaming hamarosan nemcsak a játék, hanem a számítástechnika más területeinek következő generációja lesz. A felhőalapú játék a kliens/szerver modell csúcsa. Ez a modell maximalizálja a háttérrendszer kezelését és minimalizálja az előtérben végzett munkát azáltal, hogy távoli szerveren tárolja a játéklogikát, és streameli a képeket/hangot az ügyfélnek. A kiszolgáló végzi a nehéz feldolgozást, így a kliens többé nincs kitéve a hardveres korlátoknak.

A Google Stadia lényegében lehetővé teszi a játékot AAA játékok (vagyis csúcskategóriás kasszasiker játékok) egy olyan felületen, mint a YouTube. Ugyanez a módszer alkalmazható más nehéz offline alkalmazásoknál is, mint például az operációs rendszer vagy a 2D/3D grafikai tervezés stb. hogy konzisztensen futtathassuk őket alacsony specifikációjú eszközökön több platformon.

Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
A technológia jövője: Képzeld el, ha a Microsoft Windows 10 futna a Chrome böngészőn?

A felhőalapú játék technikailag kihívást jelent

A játék azon ritka területek egyike, ahol állandó, gyors felhasználói reakcióra van szükség. Ha időnként 2 másodperces késéssel találkozunk az oldalra kattintva, ez elfogadható. Az élő videó streamek általában néhány másodperces késéssel jelennek meg, de továbbra is ésszerű használhatóságot kínálnak. Ha azonban a játék gyakran 500 ms-ot késik, akkor egyszerűen nem játszható. Célunk rendkívül alacsony késleltetés elérése, hogy a bemenet és a média közötti rés a lehető legkisebb legyen. Ezért a video streaming hagyományos megközelítése itt nem alkalmazható.

Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
Általános felhő játéksablon

Nyílt forráskódú projekt CloudRetro

Úgy döntöttem, készítek egy tesztmintát egy felhőjátékból, hogy megnézzem, mindez lehetséges-e ilyen szigorú hálózati korlátozások mellett. A Golangot választottam a koncepció bizonyítására, mert ez volt az a nyelv, amelyet a legjobban ismertem, és sok más okból is alkalmas volt erre a megvalósításra, ahogy később felfedeztem. A Go egyszerű és nagyon gyorsan fejlődik; A Go csatornái nagyszerűek a többszálú kezelés kezelésére.

Terv CloudRetro.io egy nyílt forráskódú felhőalapú játékszolgáltatás retro játékokhoz. A projekt célja, hogy a legkényelmesebb játékélményt hozza a hagyományos retro játékokba, és hozzáadja a többjátékos módot.
Itt tudhat meg többet a projektről: https://github.com/giongto35/cloud-game.

CloudRetro funkció

A CloudRetro retro játékokat használ a felhőalapú játék erejének bemutatására. Ez lehetővé teszi számos egyedi játékélmény megszerzését.

  • A játék hordozhatósága
    • Azonnali lejátszás az oldal megnyitásakor; nincs szükség letöltésre vagy telepítésre
    • Mobilböngészőben működik, így futtatásához nincs szükség szoftverre

  • A játékmenetek több eszköz között is megoszthatók, és a felhőben tárolhatók a következő bejelentkezéshez
  • A játék streamelhető, vagy akár több felhasználó is játszhatja egyszerre:
    • Crowdplay, mint a TwitchPlayPokemon, csak több platformon és valós időben
    • Offline játékok online. Sok felhasználó hálózat beállítása nélkül is tud játszani. A Samurai Shodownt mostantól 2 játékos játszhatja a CloudRetro hálózaton keresztül

    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    Online többjátékos játék demóverziója különböző eszközökön

    Infrastruktúra

    Követelmények és technológiai halom

    Az alábbiakban felsoroljuk azokat a követelményeket, amelyeket a projekt elindítása előtt állítottam fel.

    1. Egy játékos
    Ez a követelmény itt talán nem tűnik túl fontosnak vagy nyilvánvalónak, de ez az egyik kulcsfontosságú dolog, lehetővé teszi, hogy a felhőalapú játék a lehető legtávolabb maradjon a hagyományos streaming szolgáltatásoktól. Ha egyjátékos játékra koncentrálunk, akkor megszabadulhatunk a központosított szervertől vagy CDN-től, mert nem kell tömegekhez streamelnünk. Ahelyett, hogy adatfolyamokat töltenének fel egy fogadó kiszolgálóra, vagy csomagokat továbbítanának egy központi WebSocket szerverre, a szolgáltatásfolyamok közvetlenül a felhasználóhoz jutnak el egy peer-to-peer WebRTC kapcsolaton keresztül.

    2. Alacsony késleltetésű médiafolyam
    A Stadiáról olvasva gyakran látom, hogy egyes cikkekben említik a WebRTC-t. Rájöttem, hogy a WebRTC egy kiemelkedő technológia, és tökéletes a felhőalapú játékokhoz. A WebRTC egy olyan projekt, amely valós idejű kommunikációt biztosít webböngészőknek és mobilalkalmazásoknak egy egyszerű API-n keresztül. Peer-to-peer kapcsolatot biztosít, médiára van optimalizálva, és szabványos beépített kodekekkel rendelkezik, mint például a VP8 és a H264.

    Előnyben részesítettem a lehető legjobb felhasználói élmény biztosítását, mint a jó minőségű grafika fenntartását. Néhány veszteség elfogadható az algoritmusban. A Google Stadiának van egy további lépése, hogy csökkentse a képméretet a szerveren, és a képkockákat a rendszer jobb minőségre skálázza, mielőtt továbbítaná őket a többieknek.

    3. Elosztott infrastruktúra földrajzi útválasztással
    Nem számít, mennyire optimalizált a tömörítési algoritmus és a kód, a hálózat továbbra is a döntő tényező, amely leginkább hozzájárul a késleltetéshez. Az architektúrának rendelkeznie kell egy olyan mechanizmussal, amely párosítja a felhasználóhoz legközelebbi kiszolgálót az oda-vissza úti idő (RTT) csökkentése érdekében. Az architektúrának 1 koordinátorral és több streaming szerverrel kell rendelkeznie, amelyek szerte a világon vannak elosztva: US West, US East, Europe, Singapore, China. Minden streaming szervert teljesen el kell különíteni. A rendszer módosíthatja elosztását, amikor egy szerver csatlakozik a hálózathoz, vagy elhagyja azt. Így nagy forgalom esetén további szerverek hozzáadása lehetővé teszi a vízszintes méretezést.

    4. Böngésző kompatibilitás
    A felhőalapú játék akkor a legjobb, ha a legkevesebbet követeli meg a felhasználóktól. Ez azt jelenti, hogy böngészőben is futtatható. A böngészők segítenek abban, hogy a játékélmény a lehető legkényelmesebb legyen a felhasználók számára, megkímélve őket a szoftver és hardver telepítésétől. A böngészők emellett többplatformos funkcionalitást biztosítanak a mobil és az asztali verziók között. Szerencsére a WebRTC számos böngészőben jól támogatott.

    5. A játékfelület és a szolgáltatás egyértelmű szétválasztása
    A felhőalapú játékszolgáltatást platformnak tekintem. Mindenkinek képesnek kell lennie bármit csatlakoztatni a platformhoz. Most integráltam LibRetro felhős játékszolgáltatással, mert a LibRetro gyönyörű játékemulátor felületet kínál az olyan retro játékokhoz, mint a SNES, GBA, PS.

    6. Szobák többjátékos játékhoz, tömegjátékhoz és külső kapcsolathoz (mély kapcsolat) a játékhoz
    A CloudRetro számos új játékmenetet támogat, mint például a CrowdPlay és az Online MultiPlayer retro játékokhoz. Ha több felhasználó nyitja meg ugyanazt a mélyhivatkozást különböző számítógépeken, ugyanazt a futó játékot látják, és még csatlakozhatnak is hozzá.

    Sőt, a játékállapotokat felhőtárhelyen tárolják. Ezzel a felhasználók bármikor folytathatják a játékot bármely más eszközön.

    7. Vízszintes méretezés
    Mint manapság minden SAAS-t, a felhőalapú játékot is úgy kell megtervezni, hogy vízszintesen méretezhető legyen. A koordinátor-dolgozó kialakítás lehetővé teszi, hogy több alkalmazottat vegyen fel a nagyobb forgalom kiszolgálása érdekében.

    8. Nincs kapcsolat egyetlen felhőhöz
    A CloudRetro infrastruktúráját különböző felhőszolgáltatók (Digital Ocean, Alibaba, egyéni szolgáltató) tárolják a különböző régiókban. Engedélyezem a Docker-tárolóban való futtatást az infrastruktúra számára, és konfigurálom a hálózati beállításokat egy bash-szkript segítségével, hogy elkerüljem, hogy egyetlen felhőszolgáltatóhoz zárjak. Ha ezt kombináljuk a WebRTC NAT Traversal szolgáltatásával, rugalmasan telepíthetjük a CloudRetro-t bármely felhőplatformon, sőt bármely felhasználó gépén.

    Építészeti tervezés

    Munkás: (vagy a fent említett streaming szerver) megsokszorozza a játékokat, futtatja a kódolási folyamatot, és a kódolt médiát továbbítja a felhasználóknak. A Worker-példányok az egész világon el vannak terjesztve, és minden dolgozó egyszerre több felhasználói munkamenetet is kezelhet.

    Koordinátor: felelős azért, hogy az új felhasználót a streamelésre legalkalmasabb dolgozóval párosítsa. A koordinátor a WebSocketen keresztül kommunikál a dolgozókkal.

    A játék állapotának tárolása: központi távoli tároló minden játékállapothoz. Ez a tároló fontos funkciókat biztosít, mint például a távoli mentés/betöltés.

    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    A CloudRetro legfelső szintű architektúrája

    Egyéni szkript

    Amikor egy új felhasználó megnyitja a CloudRetro alkalmazást az alábbi ábrán látható 1. és 2. lépésben, a koordinátor az elérhető dolgozók listájával együtt az első oldalra kerül. Ezt követően a 3. lépésben az ügyfél HTTP ping kéréssel kiszámítja az összes jelölt késleltetését. Ezt a késések listáját ezután visszaküldik a koordinátornak, hogy meghatározhassa a felhasználó kiszolgálására legmegfelelőbb dolgozót. Az alábbi 4. lépés létrehozza a játékot. WebRTC adatfolyam-kapcsolat jön létre a felhasználó és a hozzárendelt dolgozó között.
    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    Felhasználói szkript a hozzáférés megszerzése után

    Mi van a munkás belsejében

    A játék- és adatfolyam-folyamatokat a dolgozóban elkülönítve tárolják, és ott az interfészen keresztül információt cserélnek. Jelenleg ez a kommunikáció a memóriában lévő adatok átvitelével történik Golang csatornák ugyanabban a folyamatban. A következő cél a szegregáció, azaz. a játék független elindítása egy másik folyamatban.

    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    A munkavállalói alkatrészek kölcsönhatása

    Fő összetevők:

    • WebRTC: egy kliens komponens, amely elfogadja a felhasználói bevitelt, és kódolt adathordozót ad ki a szerverről.
    • Játék emulátor: játék komponens. A Libretro könyvtárnak köszönhetően a rendszer képes futtatni a játékot ugyanazon a folyamaton belül, és belsőleg elfogja a médiát és a bemeneti adatfolyamot.
    • A játékon belüli képkockákat rögzíti és elküldi a kódolónak.
    • Kép/audio kódoló: egy kódolási folyamat, amely médiakockákat vesz fel, kódolja azokat a háttérben, és kódolt képeket/hangot ad ki.

    Реализация

    A CloudRetro a WebRTC-re támaszkodik gerinctechnológiájaként, ezért mielőtt belemerülnék a Golang megvalósítás részleteibe, úgy döntöttem, hogy magáról a WebRTC-ről beszélek. Ez egy csodálatos technológia, amely nagymértékben segített abban, hogy elérjem a másodperc alatti késleltetést a streaming adatokhoz.

    WebRTC

    A WebRTC-t úgy tervezték, hogy egyszerű API-k segítségével kiváló minőségű peer-to-peer kapcsolatokat biztosítson natív mobilalkalmazásokon és böngészőkön.

    NAT átjárás

    A WebRTC a NAT Traversal funkciójáról ismert. A WebRTC-t peer-to-peer kommunikációra tervezték. Célja, hogy megtalálja a legmegfelelőbb közvetlen útvonalat, elkerülve a NAT átjárókat és tűzfalakat a peer-to-peer kommunikációhoz egy ún. ICE. Ennek a folyamatnak a részeként a WebRTC API-k STUN szerverek segítségével megtalálják az Ön nyilvános IP-címét, és továbbítják azt a közvetítő szervernek (FORDULAT), ha nem létesíthető közvetlen kapcsolat.

    A CloudRetro azonban nem használja ki teljesen ezt a funkciót. Peer-to-peer kapcsolatai nem a felhasználók, hanem a felhasználók és a felhőkiszolgálók között léteznek. A modell szerveroldala kevesebb közvetlen kommunikációs korlátozással rendelkezik, mint egy tipikus felhasználói eszköz. Ez lehetővé teszi a bejövő portok előzetes megnyitását vagy a nyilvános IP-címek közvetlen használatát, mivel a szerver nem áll NAT mögött.

    Korábban a projektet a Cloud Gaming játékterjesztési platformjává akartam alakítani. Az ötlet az volt, hogy lehetővé tegyék a játékok készítői számára, hogy játékokat és streamelési forrásokat biztosítsanak. A felhasználók pedig közvetlenül kapcsolatba lépnének a szolgáltatókkal. Ilyen decentralizált módon a CloudRetro csak egy keretrendszer a harmadik féltől származó streamelési erőforrások felhasználókhoz való csatlakoztatásához, így jobban méretezhető, ha már nincs hosztolva. A WebRTC NAT Traversal szerepe nagyon fontos, hogy megkönnyítse a peer-to-peer kapcsolat inicializálását harmadik féltől származó streaming erőforrásokon, megkönnyítve az alkotó számára a hálózathoz való csatlakozást.

    Videó tömörítés

    A videotömörítés a csővezeték nélkülözhetetlen része, és nagyban hozzájárul a zökkenőmentes áramláshoz. Noha nem szükséges ismerni a VP8/H264 videókódolás minden részletét, a fogalmak megértése segíthet megérteni a streaming videó sebességi beállításait, a váratlan viselkedések hibakeresését és a késleltetés beállítását.

    A videó tömörítése egy streaming szolgáltatáshoz kihívást jelent, mert az algoritmusnak biztosítania kell, hogy a teljes kódolási idő + hálózati átviteli idő + dekódolási idő a lehető legalacsonyabb legyen. Ezenkívül a kódolási folyamatnak következetesnek és folyamatosnak kell lennie. Néhány kódolási kompromisszum nem érvényes – például nem részesíthetjük előnyben a hosszú kódolási időket a kisebb fájlméretekkel és dekódolási időkkel szemben, illetve nem alkalmazhatunk következetlen tömörítést.

    A videotömörítés mögött meghúzódó ötlet az, hogy kiküszöbölje a szükségtelen információkat, miközben a felhasználók számára elfogadható pontossági szintet tart fenn. Az egyes statikus képkockák kódolása mellett az algoritmus az előző és a következő képkockákból következtet az aktuális képkockára, így csak azok különbségét küldi el. Amint a Pacman példájából látható, csak a differenciálpontokat továbbítják.

    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    Videókockák összehasonlítása Pacman példaként

    Hangtömörítés

    Hasonlóképpen, a hangtömörítési algoritmus kihagyja az emberek által nem észlelhető adatokat. Az Opus jelenleg a legjobban teljesítő audiokodek. Úgy tervezték, hogy hanghullámot továbbítson egy rendezett datagram protokollon, például az RTP-n (Real Time Transport Protocol) keresztül. A késleltetési ideje alacsonyabb, mint az mp3 és az aac, a minősége pedig jobb. A késleltetés általában 5-66,5 ms körül van.

    Pion, WebRTC Golangban

    pion egy nyílt forráskódú projekt, amely a WebRTC-t Golangba hozza. A natív C++ WebRTC-könyvtárak szokásos burkolása helyett a Pion a WebRTC natív Golang-megvalósítása jobb teljesítménnyel, Go-integrációval és verziókezeléssel a WebRTC protokollokon.

    A könyvtár emellett lehetővé teszi a streamelést is sok nagyszerű beépített beépítettséggel, másodperc alatti késleltetéssel. Megvan a saját megvalósítása a STUN, DTLS, SCTP stb. valamint néhány kísérlet a QUIC-cal és a WebAssembly-vel. Ez a nyílt forráskódú könyvtár maga egy igazán jó tanulási forrás kiváló dokumentációval, hálózati protokoll-megvalósításokkal és remek példákkal.

    A Pion közösség, amelyet egy nagyon szenvedélyes alkotó vezet, meglehetősen élénk, sok minőségi vita folyik a WebRTC-ről. Ha érdekel ez a technológia, csatlakozz http://pion.ly/slack – sok új dolgot fogsz megtanulni.

    CloudRetro írása Golang nyelven

    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    Munkavállaló megvalósítása a Go-ban

    Irány a csatornák akcióban

    A Go gyönyörű csatornakialakításának köszönhetően az események streamelésével és a párhuzamossággal kapcsolatos problémák jelentősen leegyszerűsödnek. Ahogy az ábrán is látható, a különböző GoRoutine-oknak több komponense fut párhuzamosan. Mindegyik komponens kezeli állapotát és csatornákon keresztül kommunikál. Golang szelektív állítása a játékban minden alkalommal egy atomi esemény feldolgozására kényszerít (játék pipa). Ez azt jelenti, hogy ehhez a kialakításhoz nincs szükség reteszelésre. Például amikor egy felhasználó ment, a játék állapotáról teljes pillanatfelvételre van szükség. Ennek az állapotnak folyamatosnak kell maradnia, be kell jelentkezni a mentés befejezéséig. Minden játék tick alatt a háttérprogram csak egy mentési vagy beviteli műveletet tud kezelni, így a folyamatszál biztonságossá válik.

    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

    Ez a Golang-sablon tökéletesen illeszkedik a CrowdPlay és a Multiple Player használati eseteimhez. Ezt a mintát követve az összes felhasználói bemenet egy helyiségben a központi bejárati csatornába van beépítve. A játékmédia ezután ugyanabban a szobában lévő összes felhasználóhoz kerül. Ily módon elérjük a játék állapotának felosztását a különböző felhasználók több játékmenete között.

    Nyílt forráskódú felhős játék a WebRTC-n: p2p, többjátékos, nulla késleltetés
    Szinkronizálás a különböző munkamenetek között

    A Golang hátrányai

    Golang nem tökéletes. A csatorna lassú. A blokkoláshoz képest a Go csatorna egyszerűen egyszerűbb módja az egyidejű és szálas események kezelésének, de a csatorna nem nyújtja a legjobb teljesítményt. A csatorna alatt összetett blokkoló logika található. Így néhány módosítást végeztem a megvalósításon, a teljesítmény optimalizálása érdekében újra alkalmaztam a zárakat és az atomértékeket a csatornák cseréjekor.

    Ráadásul a golangi szemétgyűjtőt nem irányítják, ami néha gyanúsan hosszú szüneteket okoz. Ez nagymértékben zavarja a valós idejű streaming alkalmazást.

    PATKÓSZEG

    A projekt a meglévő nyílt forráskódú Golang VP8/H264 könyvtárat használja a médiatömörítéshez, a Libretrót pedig a játékemulátorokhoz. Mindezek a könyvtárak egyszerűen a C-könyvtár burkolói a Go-ban PATKÓSZEG. Néhány hátrányt felsorolunk ezt a bejegyzést írta Dave Cheney. Problémák, amelyekkel találkoztam:

    • képtelenség elkapni egy összeomlást a CGO-ban, még a Golang RecoveryCrash esetén sem;
    • a teljesítmény szűk keresztmetszetek azonosításának elmulasztása, amikor nem tudjuk észlelni a CGO részletes problémáit.

    Következtetés

    Elértem azt a célt, hogy megértsem a felhőalapú játékszolgáltatásokat, és létrehozzak egy olyan platformot, amely segít nosztalgikus retro játékokat játszani a barátaimmal online. Ez a projekt nem jöhetett volna létre a Pion könyvtár és a Pion közösség támogatása nélkül. Nagyon hálás vagyok az intenzív fejlesztésért. A WebRTC és a Pion által biztosított egyszerű API-k zökkenőmentes integrációt biztosítottak. Azon a héten adták ki az első proof of concept-emet, annak ellenére, hogy nem tudtam előzetesen a peer-to-peer (P2P) kommunikációt.

    A könnyű integráció ellenére a P2P streaming valóban nagyon összetett terület a számítástechnikában. A peer-to-peer munkamenet létrehozásához meg kell küzdenie a régóta fennálló hálózati architektúrák, például az IP és a NAT összetettségével. A projekten való munkám során rengeteg értékes tudást szereztem a hálózatépítésről és a teljesítményoptimalizálásról, ezért arra biztatok mindenkit, hogy próbálja ki a WebRTC segítségével P2P termékek készítését.

    A CloudRetro minden olyan használati esetet kielégít, amelyet retro játékosként vártam. Azonban úgy gondolom, hogy a projektben sok olyan terület van, amin javíthatok, mint például a hálózat megbízhatóbbá és teljesítményesebbé tétele, jobb minőségű játékgrafika biztosítása, vagy a játékok felhasználók közötti megosztásának lehetősége. Keményen dolgozom ezen. Kérlek kövess projekt és támogasd, ha tetszik.

Forrás: will.com

Hozzászólás