Služba jako produkt, infrastruktura jako služba, platforma jako služba, komunikační platforma jako služba, videokonference jako služba, a co cloudové hry jako služba? Bylo učiněno několik pokusů o vytvoření cloudových her (Cloud Gaming), například Stadia, která nedávno byla spuštěna společností Google. Stadia , ale mohou ostatní také využívat WebRTC stejně jako?
Thanh Nguyen se rozhodl prověřit tuto možnosti ve svém open-source projektu CloudRetro. CloudRetro je založen na Pion, knihovně WebRTC napsané v Go (děkuji z týmu vývojářů Pion za pomoc při přípravě tohoto článku). V tomto článku Thanh přehledně popisuje architekturu svého projektu, a také sdílí, co se naučil a s jakými výzvami se během práce setkal.
Úvod
Loni, když Google oznámil Stadia, jsem byl naprosto ohromen. Myšlenka je tak unikátní a inovativní, že jsem se neustále ptal, jak je to vůbec možné při stávajících technologiích. Touha lépe porozumět tomuto tématu mě podnítila k vytvoření vlastní verze open-source cloudové hry. Výsledek byl prostě fantastický. Níže bych chtěl sdílet proces práce na svém ročním .
TLDR: krátká prezentace se základními body
Proč mají cloudové hry budoucnost
Věřím, že Cloud Gaming brzy bude novou generací nejen her, ale i dalších oblastí informatiky. Cloudové hry jsou vrchol klient-server modelu. Tento model maximalizuje řízení backendu a minimalizuje práci frontend tím, že umístí herní logiku na vzdálený server a streamuje obrázky/audió klientovi. Server provádí náročné zpracování, takže klient už není závislý na hardwarových omezeních.
Google Stadia vlastně umožňuje hrát (tj. vysoce kvalitní blockbusterové hry) na rozhraní podobném YouTube. Stejná metodologie může být také aplikována na jiné náročné offline aplikace, jako je operační systém nebo 2D/3D grafický design, atd., abychom je mohli stabilně spouštět na zařízeních s nízkými technickými specifikacemi napříč různými platformami.

Budoucnost této technologie: představte si, kdyby Microsoft Windows 10 běžel v prohlížeči Chrome?
Cloudové hry jsou technicky složité
Hraní je jednou z těch vzácných oblastí, kde je vyžadována neustálá rychlá reakce uživatele. Pokud občas narazíme na zpoždění 2 sekundy při kliknutí na stránce, je to přijatelné. Video streamy naživu obvykle zpožďují o několik sekund, ale stále nabízejí dostatečné pohodlí při používání. Nicméně, pokud hra často zpožďuje o 500 ms, je hraní prostě nemožné. Naším cílem je dosáhnout extrémně nízkého zpoždění, aby byl rozdíl mezi vstupem a médiem co nejmenší. Proto tradiční přístup k streamování videa zde není použitelný.

Obecná šablona cloudového hraní
Otevřený projekt CloudRetro
Rozhodl jsem se vytvořit testovací vzorek cloudového hraní, abych zjistil, zda je to možné za tak přísných síťových podmínek. Pro ověření konceptu jsem zvolil Golang, protože to je jazyk, který nejlépe znám a je také vhodný pro tuto implementaci z mnoha dalších důvodů, jak se později ukázalo. Go je jednoduchý a rychle se rozvíjí; kanály v Go jsou skvělé pro řízení vícetrhu.
Projekt – cloudová herní služba s otevřeným zdrojovým kódem pro retro hry. Cílem projektu je přinést do tradičních retro her co nejpohodlnější herní zážitky a přidat více hráčů.
Podrobně se seznamte s projektem zde: .
Funkčnost CloudRetro
Pro demonstrování síly cloudového hraní se v CloudRetro používají retro hry. To umožňuje získat množství jedinečných herních zážitků.
- Přenositelnost hry
- Okamžité přehrávání při otevření stránky; není třeba stahovat ani instalovat
- Funguje v mobilním prohlížeči, takže pro spuštění není potřeba žádný software
- Herní seance lze sdílet na několika zařízeních a ukládat do cloudu pro další přihlášení
- Hru lze streamovat, nebo v ní mohou hrát najednou několik uživatelů:
- Crowdplay typu TwitchPlayPokemon, jen je to více multiplatformní a real-time
- Offline hry online. Mnoho uživatelů může hrát bez nutnosti nastavování sítě. V Samurai Shodown nyní mohou hrát 2 hráči prostřednictvím CloudRetro

Demo verze multiplayerové online hry na různých zařízeníchInfrastruktura
Požadavky a technický stack
Níže je uveden seznam požadavků, které jsem stanovil před zahájením projektu.
1. Jeden hráč
Tato požadavek se může zdát zde jako nepříliš důležitý a zřejmý, ale je to jedno z mých klíčových zjištění, které umožňuje cloudovým hrám se co nejvíce distancovat od tradičních streamovacích služeb. Pokud se zaměříme na hru pro jednoho hráče, můžeme se zbavit centralizovaného serveru nebo CDN, protože není potřeba streamovat k masám. Místo toho, abychom nahrávali streamy na náročný server nebo posílali balíčky na centralizovaný server WebSocket, jsou streamy služeb předávány uživateli přímo prostřednictvím peer-to-peer spojení WebRTC.2. Mediální stream s nízkou latencí
Při čtení o Stadia se často v některých článcích setkávám s zmínkou o WebRTC. Uvědomil jsem si, že WebRTC je vynikající technologie, která je skvěle přizpůsobena pro použití v cloudových hrách. WebRTC je projekt, který poskytuje webovým prohlížečům a mobilním aplikacím komunikaci v reálném čase prostřednictvím jednoduchého API. Zajišťuje peer-to-peer spojení optimalizované pro média a má vestavěné standardní kodeky, jako jsou VP8 a H264.Dával jsem přednost zajištění maximálního komfortu uživatelů před zachováním vysoké kvality grafiky. V algoritmu jsou povoleny určité ztráty. V Google Stadia existuje další krok ke snížení velikosti obrázku na serveru, a snímky jsou škálovány do vyšší kvality před předáním peer-to-peer uzlům.
3. Distribuovaná infrastruktura s geografickým směrováním
Bez ohledu na to, jak je optimalizován kompresní algoritmus a kód, síť zůstává rozhodujícím faktorem, který nejvíce přispívá k latenci. Architektura by měla mít mechanismus připojení nejbližšího serveru k uživateli pro snížení doby příjmu a přenosu (RTT). Architektura by měla mít 1 koordinátora a několik streamovacích serverů rozložených po celém světě: Západ USA, Východ USA, Evropa, Singapur, Čína. Všechny streamovací servery by měly být zcela izolovány. Systém může regulovat své rozdělení, když se server připojuje do sítě nebo z ní vystupuje. Tímto způsobem, při vysokém provozu, přidání dalších serverů umožňuje provádět horizontální škálování.4. Kompatibilita prohlížeče
Cloud gaming shines best when it demands as little as possible from users. This means that it can be launched in a browser. Browsers help make the gaming experience as comfortable as possible for users, freeing them from the need to install software and hardware. Browsers also help ensure cross-platform compatibility for mobile and desktop versions. Fortunately, WebRTC is well-supported across various browsers.5. Jasné oddělení herního rozhraní a služby
Považuji cloudovou herní službu za platformu. Každý by měl mít možnost připojit k platformě cokoliv. V současnosti jsem integroval s cloudovou herní službou, protože LibRetro nabízí krásné rozhraní herního emulátoru pro retro hry, jako jsou SNES, GBA, PS.6. Místnosti pro multiplayer, crowd play a externí propojení (deep-link) se hrou
CloudRetro podporuje řadu nových herních stylů, jako jsou CrowdPlay a Online MultiPlayer pro retro hry. Když několik uživatelů otevře stejný deep-link na různých počítačích, uvidí stejnou spuštěnou hru a dokonce se k ní mohou připojit.Navíc se stavy hry ukládají v cloudovém úložišti. To umožňuje uživatelům pokračovat ve hře kdykoliv na jakémkoli jiném zařízení.
7. Horizontální škálovatelnost
Stejně jako jakýkoli SAAS dnes, cloudové hry musí být navrženy tak, aby byly horizontálně škálovatelné. Konstrukce "koordinační pracovník" umožňuje přidávat více pracovníků, aby obsluhovali větší provoz.8. Žádná vazba na jedno cloudové prostředí
Infrastruktura CloudRetro je umístěna u různých cloudových poskytovatelů (Digital Ocean, Alibaba, uživatelský poskytovatel) pro různé regiony. Aktivuji spuštění v Docker kontejneru pro infrastrukturu a nastavím síťové parametry pomocí bash skriptu, aby se avoided závislost na jednom cloudovém poskytovateli. Kombinací toho s NAT Traversal v WebRTC můžeme získat flexibilitu pro nasazení CloudRetro na jakékoli cloudové platformě a dokonce na strojích jakéhokoli uživatele.Architektonický design
Pracovník: (nebo streamovací server zmíněný výše) násobí hry, spouští kódovací pipeline a přenáší zakódovaná média uživatelům. Instance pracovníka jsou rozprostřeny po celém světě a každý pracovník může zpracovávat více uživatelských relací zároveň.
Koordinátor: se stará o přiřazení nového uživatele k nejvhodnějšímu pracovníkovi pro streamování. Koordinátor komunikuje s pracovníky prostřednictvím WebSocket.
Úložiště herních stavů: centrální vzdálené úložiště všech herních stavů. Toto úložiště poskytuje důležité funkce, jako je vzdálené ukládání/nahrávání.

Vrchovatá architektura CloudRetroUživatelský scénář
Když nový uživatel otevře CloudRetro na krocích 1 a 2 zobrazených níže, koordinátor spolu se seznamem dostupných pracovníků požaduje první stránku. Poté ve kroku 3 klient vypočítá latence pro všechny kandidáty pomocí HTTP požadavku ping. Tento seznam latencí je následně odeslán zpět koordinátorovi, aby mohl určit nejvhodnějšího pracovníka pro obsluhu uživatele. Ve kroku 4 níže se vytváří hra. Mezi uživatelem a přiděleným pracovníkem se vytváří streamovací spojení WebRTC.

Uživatelský scénář po získání přístupuCo je uvnitř pracovníka
Herní a streamovací pipeline jsou uvnitř pracovníka uchovávány izolovaně a vyměňují si tam informace prostřednictvím rozhraní. V současné době je tato komunikace zajištěna prostřednictvím přenosu dat v paměti pomocí ve stejného procesu. Dalším cílem je segregace, tj. nezávislé spuštění hry v jiném procesu.

Interakce komponent pracovníkaHlavní složky:
- WebRTC: klientská komponenta, která přijímá uživatelský vstup a výstup zakódovaného média ze serveru.
- Herní emulátor: herný komponent. Díky knihovně Libretro je systém schopen spustit hru uvnitř téhož procesu a interně zachytit média a tok vstupu.
- In-game snímky jsou zachyceny a odeslány do enkodéru.
- Obrázkový/audio enkodér: kódovací pipeline, která přijímá mediální snímky, zakóduje je na pozadí a výstupy zakódované obrázky/audio.
Implementace
CloudRetro se spoléhá na WebRTC jako na klíčovou technologii, a proto jsem se před tím, než se ponořím do podrobností implementace v Golangu, rozhodl nejprve přiblížit samotný WebRTC. To je ohromující technologie, která mi výrazně pomohla dosáhnout latence streamování dat jen na zlomek sekundy.
WebRTC
WebRTC je navržen tak, aby poskytoval vysoce kvalitní peer-to-peer spojení v nativních mobilních aplikacích a v prohlížečích pomocí jednoduchých API.
NAT Traversal
WebRTC je známý svou funkcionalitou NAT Traversal. WebRTC je určen pro peer-to-peer komunikaci. Jeho cílem je najít nejvhodnější přímou trasu, aby se vyhnulo NAT bránám a firewallům pro peer-to-peer spojení prostřednictvím procesu zvaného . V rámci tohoto procesu API WebRTC zjistí vaši veřejnou IP adresu pomocí STUN serverů a přesměrují ji na server přenosu (), když nemůže být navázáno přímé spojení.
Nicméně CloudRetro tuto možnost nevyužívá zcela. Jeho peer-to-peer spojení neexistují mezi uživateli, ale mezi uživateli a cloudovými servery. Serverová část modelu má méně omezení na přímou komunikaci než běžné uživatelské zařízení. To umožňuje předběžně otevřít příchozí porty nebo používat veřejné IP adresy přímo, protože server není za NAT.
Dříve jsem chtěl proměnit projekt na platformu pro šíření her pro Cloud Gaming. Myšlenka byla umožnit tvůrcům her poskytovat hry a streamové zdroje. Uživatelé by pak interagovali přímo s poskytovateli. V této decentralizované formě je CloudRetro jen prostředím pro připojení externích streamových zdrojů k uživatelům, což z něj činí škálovatelnější, když na něm už není hostování. Role WebRTC NAT Traversal je zde velmi důležitá pro usnadnění iniciace peer-to-peer spojení na externích streamových zdrojích, což zjednodušuje připojení tvůrce k síti.
Kompresi videa
Kompresia videa je nezbytnou součástí pipeliningu, která výrazně přispívá k plynulosti toku. I když není nutné znát všechny detaily kódování videa ve formátu VP8/H264, pochopení konceptu pomáhá porozumět parametrům rychlosti streamovaného videa, ladit neočekávané chování a nastavovat zpoždění.
Kompresia videa pro streamovací službu je složitý úkol, protože algoritmus musí zajistit, že celkový čas kódování + čas přenosu po síti + čas dekódování je co nejmenší. Kromě toho musí být proces kódování konzistentní a nepřetržitý. Některé vzájemné ústupky při kódování nejsou použitelné – například nemůžeme upřednostnit delší čas kódování před menší velikostí souboru a časem dekódování, nebo použít nekonzistentní kompresi.
Myšlenka komprese videa spočívá v tom, že se vyloučí zbytečné bity informací, přičemž se zachovává přijatelná úroveň přesnosti pro uživatele. Kromě kódování jednotlivých statických snímků algoritmus odvozuje aktuální snímek z předchozího a následujícího, takže se přenáší pouze jejich rozdíl. Jak je vidět na příkladu s Pacmanem, přenášejí se pouze diferenciální body.

Srovnání videokadru na příkladu PacmanaKompresia audia
Podobně jako u videa, algoritmus komprese zvuku vynechává data, která nemohou být vnímána člověkem. Opus je v současnosti audio kodek s nejlepšími výkony. Byl navržen pro přenos zvukové vlny prostřednictvím protokolu uspořádaných datagramů, jako je RTP (Real-Time Transport Protocol – protokol pro přenos v reálném čase). Jeho zpoždění je menší než u mp3 a aac, a kvalita je vyšší. Zpoždění obvykle činí kolem 5~66,5 ms.
Pion, WebRTC v Golangu
je projekt s otevřeným zdrojovým kódem, který přenáší WebRTC na Golang. Místo obvyklého wrapperu nativních C++ knihoven WebRTC je Pion nativní implementací WebRTC v Golangu s nejlepšími výkony, integrací s Go a také správou verzí protokolů WebRTC.
Knihovna také poskytuje streamování dat s mnoha skvělými vestavěnými moduly s latencí méně než jednu sekundu. Má vlastní implementaci STUN, DTLS, SCTP atd. a některé experimenty s QUIC a WebAssembly. Tato open-source knihovna je sama o sobě opravdu dobrým zdrojem pro učení s vynikající dokumentací, implementací síťových protokolů a skvělými příklady.
Komunita Pion, vedená velmi vášnivým tvůrcem, je poměrně živá, probíhá zde mnoho kvalitních diskusí o WebRTC. Pokud vás tato technologie zajímá, připojte se k – naučíte se mnoho nového.
Psání CloudRetro v Golangu

Implementace pracovníka v GoKanály Go v akci
Díky krásnému designu kanálů Go se problémy se streamováním událostí a paralelismem výrazně zjednodušují. Jak ukazuje diagram, v různých GoRoutine běží paralelně několik komponent. Každá komponenta spravuje svůj stav a komunikuje prostřednictvím kanálů. Výběrové tvrzení Golang nutí zpracovávat jedno atomové událost v každém herním taktu. To znamená, že pro takový design není potřeba zámek. Například, když uživatel ukládá, je zapotřebí kompletní snímek stavu hry. Tento stav musí zůstat kontinuální, vykonávající vstup, dokud není uložení dokončeno. Během každého herního taktu může backend zpracovávat pouze operaci ukládání nebo vstupu, což činí proces thread-safe.
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
Tento Golang vzor je skvěle vhodný pro mé scénáře použití CrowdPlay a Multiple Player. Následováním tohoto vzoru se všechny uživatelské vstupy v jedné místnosti skládají do centrálního vstupního kanálu. Herní média se poté rozesílají všem uživatelům v jedné místnosti. Takto dosahujeme rozdělení stavu hry mezi několika herními sezeními různých uživatelů.

Synchronizace mezi různými sezenímiNevýhody Golangu
Golang není dokonalý. Kanál je pomalý. Ve srovnání s blokováním kanál Go představuje jednodušší metodu zpracování paralelních a streamovaných událostí, ale kanál neposkytuje nejlepší výkon. Pod kanálem se skrývá složitá logika blokování. Proto jsem provedl některé úpravy v implementaci, znovu použil blokace a atomické hodnoty při náhradě kanálů pro optimalizaci výkonu.
Kromě toho je garbage collector v Golangu neřízený, což občas způsobuje podezřele dlouhé pauzy. To výrazně brání výkonu streamovací aplikace v reálném čase.
CGO
V projektu je použita existující open source knihovna VP8/H264 golangu pro kompresi médií a Libretro pro herní emulátory. Všechny tyto knihovny jsou jen obálky C knihovny v Go s využitím . Některé z nedostatků jsou uvedeny v . Problémy, se kterými jsem se setkal:
- nemožnost zachytit pád v CGO, i s pomocí Golang RecoveryCrash;
- nemožnost určit úzké místo v výkonu, když nemůžeme odhalit detailní problémy v CGO.
Závěr
Dosáhl jsem svého cíle – porozuměl jsem cloudovým herním službám a vytvořil platformu, která pomáhá hrát nostalgické retro hry online s mými přáteli. Vytvoření tohoto projektu by nebylo možné bez knihovny Pion a podpory komunity Pion. Jsem velmi vděčný za její intenzivní rozvoj. Jednoduchá API poskytnutá WebRTC a Pion zajistila plynulou integraci. Můj první důkaz konceptu byl vydán ve stejné týdny, přestože jsem předem nevěděl o peer-to-peer (P2P) připojení.
Navzdory snadnosti integrace je P2P streamování opravdu velmi komplexní oblast v počítačové vědě. Musí se vypořádat se složitostí mnohaletých síťových architektur, jako je IP a NAT, aby vytvořilo peer-to-peer relaci. Během práce na tomto projektu jsem získal mnoho cenných znalostí o sítích a optimalizaci výkonu, a proto doporučuji všem, aby se pokusili vytvořit P2P produkty pomocí WebRTC.
CloudRetro splňuje všechny scénáře použití, které jsem očekával, jakožto retro hráč. Nicméně si myslím, že existuje mnoho oblastí v projektu, které mohu zlepšit, například učinit síť spolehlivější a výkonnější, zajistit vyšší kvalitu grafiky her nebo možnost sdílení her mezi uživateli. Usilovně na tom pracuji. Prosím, sledujte a podpořte ho, pokud se vám líbí.
Zdroj: habr.com







