Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero

Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
Programari com a servei, infraestructura com a servei, plataforma com a servei, plataforma de comunicació com a servei, videoconferència com a servei, què passa amb els jocs al núvol com a servei? Ja hi ha hagut diversos intents de crear jocs al núvol (Cloud Gaming), com ara Stadia, llançat recentment per Google. Estadi no és nou a WebRTC, però altres poden utilitzar WebRTC de la mateixa manera?

Thanh Nguyen va decidir provar aquesta oportunitat al seu projecte de codi obert CloudRetro. CloudRetro es basa en Pion, popular Biblioteca WebRTC basada en Go (gràcies Es mostra de l'equip de desenvolupament de Pion per la seva ajuda en la preparació d'aquest article). En aquest article, Thanh ofereix una visió general de l'arquitectura del seu projecte, i també parla de quines coses útils va aprendre i quins reptes va trobar durant el seu treball.

Entrada

L'any passat, quan Google va anunciar Stadia, em va sorprendre. La idea és tan única i innovadora que em preguntava constantment com era possible fins i tot amb la tecnologia existent. El desig d'entendre millor aquest tema em va impulsar a crear la meva pròpia versió d'un joc al núvol de codi obert. El resultat va ser senzillament fantàstic. A continuació m'agradaria compartir el procés de treball del meu any projecte.

TLDR: versió de diapositives curta amb ressalts

Per què els jocs al núvol són el futur

Crec que el Cloud Gaming aviat es convertirà en la propera generació no només de jocs, sinó també d'altres àrees de la informàtica. Els jocs al núvol són el cim del model client/servidor. Aquest model maximitza la gestió del backend i minimitza el treball del frontend allotjant la lògica del joc en un servidor remot i transmetent imatges/àudio al client. El servidor fa el processament pesat perquè el client ja no estigui a mercè de les limitacions de maquinari.

Google Stadia bàsicament et permet jugar Jocs AAA (és a dir, jocs de gran èxit) en una interfície com YouTube. La mateixa metodologia es pot aplicar a altres aplicacions pesades fora de línia com el sistema operatiu o el disseny gràfic 2D/3D, etc. de manera que els puguem executar de manera coherent en dispositius de baixes especificacions a diverses plataformes.

Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
El futur d'aquesta tecnologia: imagineu-vos si Microsoft Windows 10 funcionés al navegador Chrome?

Els jocs al núvol són un repte tècnic

El joc és una d'aquelles àrees rares on es requereix una resposta constant i ràpida de l'usuari. Si de tant en tant ens trobem amb un retard de 2 segons en fer clic en una pàgina, això és acceptable. Els fluxos de vídeo en directe tendeixen a retardar-se uns segons, però encara ofereixen una usabilitat raonable. Tanmateix, si el joc sovint es retarda 500 ms, simplement no es pot jugar. El nostre objectiu és aconseguir una latència extremadament baixa perquè la bretxa entre l'entrada i els mitjans sigui el més petit possible. Per tant, l'enfocament tradicional de la transmissió de vídeo no és aplicable aquí.

Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
Plantilla de joc de núvol general

Projecte de codi obert CloudRetro

Vaig decidir crear una mostra de prova d'un joc al núvol per veure si tot això era possible amb restriccions de xarxa tan estretes. Vaig triar Golang per a la prova de concepte perquè era l'idioma amb el qual estava més familiaritzat i s'adaptava molt bé a aquesta implementació per moltes altres raons, com vaig descobrir més tard. Go és senzill i es desenvolupa molt ràpidament; Els canals de Go són excel·lents per gestionar el multithreading.

Projecte CloudRetro.io és un servei de jocs al núvol de codi obert per a jocs retro. L'objectiu del projecte és aportar l'experiència de joc més còmoda als jocs retro tradicionals i afegir multijugador.
Podeu obtenir més informació sobre el projecte aquí: https://github.com/giongto35/cloud-game.

Funcionalitat CloudRetro

CloudRetro utilitza jocs retro per demostrar el poder dels jocs al núvol. El que et permet obtenir moltes experiències de joc úniques.

  • Portabilitat del joc
    • Reproducció instantània en obrir la pàgina; no cal descàrrega ni instal·lació
    • Funciona en un navegador mòbil, de manera que no es necessita cap programari per executar-lo

  • Les sessions de joc es poden compartir en diversos dispositius i emmagatzemar-les al núvol per a la propera vegada que inicieu sessió
  • El joc es pot reproduir en streaming o pot ser jugat per diversos usuaris alhora:
    • Crowdplay com TwitchPlayPokemon, només més multiplataforma i més en temps real
    • Jocs fora de línia en línia. Molts usuaris poden jugar sense configurar una xarxa. Samurai Shodown ara el poden jugar 2 jugadors a través de la xarxa CloudRetro

    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Versió de demostració del joc multijugador en línia en diferents dispositius

    Infraestructura

    Requisits i pila de tecnologia

    A continuació es mostra una llista de requisits que he establert abans de començar el projecte.

    1. Un jugador
    Aquest requisit pot no semblar massa important o obvi aquí, però és un dels meus punts clau, permet que els jocs al núvol es mantinguin el més lluny possible dels serveis de transmissió tradicionals. Si ens centrem en un joc per a un sol jugador, podem desfer-nos d'un servidor centralitzat o CDN perquè no hem de transmetre a les masses. En lloc de carregar fluxos a un servidor receptor o passar paquets a un servidor WebSocket centralitzat, els fluxos de servei es lliuren directament a l'usuari mitjançant una connexió WebRTC peer-to-peer.

    2. Flux de mitjans de baixa latència
    Llegint sobre Stadia, sovint veig que WebRTC es menciona en alguns articles. Em vaig adonar que WebRTC és una tecnologia excel·lent i és perfecta per utilitzar-la en jocs al núvol. WebRTC és un projecte que proporciona als navegadors web i aplicacions mòbils comunicació en temps real mitjançant una senzilla API. Proporciona connectivitat peer-to-peer, està optimitzat per a mitjans i té còdecs estàndard integrats com ara VP8 i H264.

    Vaig prioritzar assegurar la millor experiència d'usuari possible per sobre de mantenir gràfics d'alta qualitat. Algunes pèrdues són acceptables en l'algorisme. Google Stadia té un pas addicional per reduir la mida de la imatge al servidor i els fotogrames s'augmenten a una qualitat més alta abans de transmetre'ls als companys.

    3. Infraestructura distribuïda amb encaminament geogràfic
    Per molt optimitzats que estiguin l'algorisme i el codi de compressió, la xarxa continua sent el factor decisiu que més contribueix a la latència. L'arquitectura ha de tenir un mecanisme per emparellar el servidor més proper a l'usuari per reduir el temps d'anada i tornada (RTT). L'arquitectura ha de tenir 1 coordinador i diversos servidors de streaming distribuïts per tot el món: EUA Oest, EUA Est, Europa, Singapur, Xina. Tots els servidors de transmissió han d'estar completament aïllats. El sistema pot ajustar la seva distribució quan un servidor s'uneix o surt de la xarxa. Així, amb un gran trànsit, afegir servidors addicionals permet l'escalat horitzontal.

    4. Compatibilitat del navegador
    Els jocs al núvol són el millor quan requereixen el mínim dels usuaris. Això vol dir que és possible executar-se en un navegador. Els navegadors ajuden a fer que l'experiència de joc sigui el més còmoda possible per als usuaris, estalviant-los la instal·lació de programari i maquinari. Els navegadors també ajuden a oferir una funcionalitat multiplataforma entre les versions mòbils i d'escriptori. Afortunadament, WebRTC és compatible amb diversos navegadors.

    5. Separació clara de la interfície del joc i el servei
    Veig el servei de jocs al núvol com una plataforma. Tothom hauria de poder connectar qualsevol cosa a la plataforma. Ara m'he integrat LibRetro amb el servei de jocs al núvol perquè LibRetro ofereix una bella interfície d'emulador de jocs per a jocs retro com SNES, GBA, PS.

    6. Sales per a multijugador, joc en grup i enllaços externs (enllaç profund) amb el joc
    CloudRetro admet molts jocs nous, com ara CrowdPlay i Online Multiplayer per a jocs retro. Si diversos usuaris obren el mateix enllaç profund en diferents ordinadors, veuran el mateix joc en marxa i fins i tot podran unir-s'hi.

    A més, els estats del joc s'emmagatzemen al núvol. Això permet als usuaris continuar jugant en qualsevol moment en qualsevol altre dispositiu.

    7. Escalat horitzontal
    Com qualsevol SAAS actual, els jocs al núvol s'han de dissenyar per ser escalables horitzontalment. El disseny del coordinador-treballador us permet afegir més treballadors per atendre més trànsit.

    8. No hi ha connexió amb un núvol
    La infraestructura de CloudRetro està allotjada en diferents proveïdors de núvol (Digital Ocean, Alibaba, proveïdor personalitzat) per a diferents regions. Habilita l'execució en un contenidor Docker per a la infraestructura i configure la configuració de la xarxa mitjançant un script bash per evitar estar bloquejat en un únic proveïdor de núvol. En combinar això amb NAT Traversal a WebRTC, podem tenir la flexibilitat de desplegar CloudRetro a qualsevol plataforma de núvol i fins i tot a les màquines de qualsevol usuari.

    Diseny arquitectònic

    Treballador: (o el servidor de reproducció esmentat anteriorment) multiplica els jocs, executa la canalització de codificació i transmet els mitjans codificats als usuaris. Les instàncies de treballador es distribueixen arreu del món i cada treballador pot gestionar diverses sessions d'usuari simultàniament.

    Coordinador: s'encarrega de vincular el nou usuari amb el treballador més adequat per a la transmissió. El coordinador interactua amb els treballadors mitjançant WebSocket.

    Emmagatzematge de l'estat del joc: emmagatzematge remot central per a tots els estats del joc. Aquest emmagatzematge proporciona funcions importants com ara desar/carregar a distància.

    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Arquitectura de primer nivell de CloudRetro

    Script personalitzat

    Quan un nou usuari obre CloudRetro en els passos 1 i 2 que es mostren a la figura següent, el coordinador juntament amb la llista de treballadors disponibles es demana a la primera pàgina. Després d'això, al pas 3, el client calcula els retards per a tots els candidats mitjançant una sol·licitud de ping HTTP. Aquesta llista de retards s'envia de nou al coordinador perquè pugui determinar el treballador més adequat per atendre l'usuari. El pas 4 següent crea el joc. S'estableix una connexió de streaming WebRTC entre l'usuari i el treballador assignat.
    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Script d'usuari després d'obtenir accés

    Què hi ha dins del treballador

    Els canals de joc i de streaming s'emmagatzemen a l'interior del treballador de manera aïllada i hi intercanvien informació a través de la interfície. Actualment, aquesta comunicació es realitza mitjançant la transferència de dades a la memòria via Canals del Golang en el mateix procés. El següent objectiu és la segregació, és a dir. llançament independent del joc en un altre procés.

    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Interacció dels components del treballador

    Components principals:

    • WebRTC: un component de client que accepta l'entrada de l'usuari i emet mitjans codificats des del servidor.
    • Emulador de jocs: component del joc. Gràcies a la biblioteca Libretro, el sistema és capaç d'executar el joc dins del mateix procés i interceptar internament els mitjans i el flux d'entrada.
    • Els fotogrames del joc es capturen i s'envien al codificador.
    • Codificador d'imatge/àudio: una canalització de codificació que pren fotogrames multimèdia, els codifica en segon pla i emet les imatges/àudio codificats.

    Implementació

    CloudRetro es basa en WebRTC com a tecnologia troncal, així que abans d'aprofundir en els detalls de la implementació de Golang, vaig decidir parlar del mateix WebRTC. Aquesta és una tecnologia increïble que m'ha ajudat molt a aconseguir una latència inferior al segon per a la transmissió de dades.

    WebRTC

    WebRTC està dissenyat per oferir connexions peer-to-peer d'alta qualitat en aplicacions mòbils i navegadors nadius mitjançant API simples.

    Travessia NAT

    WebRTC és conegut per la seva funcionalitat NAT Traversal. WebRTC està dissenyat per a la comunicació peer-to-peer. El seu objectiu és trobar la ruta directa més adequada, evitant passarel·les NAT i tallafocs per a la comunicació peer-to-peer mitjançant un procés anomenat ICE. Com a part d'aquest procés, les API de WebRTC troben la vostra adreça IP pública mitjançant servidors STUN i l'envien al servidor de retransmissió (TORNAR) quan no es pot establir una connexió directa.

    No obstant això, CloudRetro no aprofita plenament aquesta funció. Les seves connexions peer-to-peer no existeixen entre usuaris, sinó entre usuaris i servidors en núvol. El costat del servidor del model té menys restriccions de comunicació directa que un dispositiu d'usuari típic. Això us permet obrir prèviament els ports d'entrada o utilitzar directament adreces IP públiques, ja que el servidor no està darrere de NAT.

    Anteriorment, volia convertir el projecte en una plataforma de distribució de jocs per a Cloud Gaming. La idea era permetre als creadors de jocs oferir jocs i recursos de streaming. I els usuaris interactuarien directament amb els proveïdors. D'aquesta manera descentralitzada, CloudRetro és només un marc per connectar recursos de transmissió de tercers als usuaris, fent-lo més escalable quan ja no està allotjat. El paper de WebRTC NAT Traversal aquí és molt important per facilitar la inicialització de la connexió peer-to-peer en recursos de transmissió de tercers, facilitant la connexió del creador a la xarxa.

    Compressió de vídeo

    La compressió de vídeo és una part indispensable del pipeline i contribueix en gran mesura a un flux suau. Tot i que no és necessari conèixer tots els detalls de la codificació de vídeo VP8/H264, entendre els conceptes us pot ajudar a comprendre les opcions de velocitat de transmissió de vídeo, depurar comportaments inesperats i ajustar la latència.

    Comprimir vídeo per a un servei de transmissió és un repte perquè l'algoritme ha de garantir que el temps total de codificació + temps de transmissió de xarxa + temps de descodificació sigui el més baix possible. A més, el procés de codificació ha de ser coherent i continu. Algunes compensacions de codificació no s'apliquen; per exemple, no podem afavorir temps de codificació llargs per mides de fitxers i temps de descodificació més petits, ni utilitzar compressió inconsistent.

    La idea darrere de la compressió de vídeo és eliminar fragments d'informació innecessaris mantenint un nivell acceptable de precisió per als usuaris. A més de codificar fotogrames d'imatge estàtiques individuals, l'algorisme dedueix el fotograma actual dels anteriors i els següents, de manera que només s'envia la seva diferència. Com es pot veure a l'exemple amb Pacman, només es transmeten punts diferencials.

    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Comparació de fotogrames de vídeo utilitzant Pacman com a exemple

    Compressió d'àudio

    De la mateixa manera, l'algoritme de compressió d'àudio omet dades que els humans no poden percebre. Actualment, Opus és el còdec d'àudio amb millor rendiment. Està dissenyat per transmetre una ona d'àudio mitjançant un protocol de datagrama ordenat com RTP (Protocol de transport en temps real). La seva latència és inferior a l'mp3 i aac, i la qualitat és més alta. La latència sol ser d'uns 5 ~ 66,5 ms.

    Pion, WebRTC a Golang

    Peó és un projecte de codi obert que porta WebRTC a Golang. En lloc de l'embolcall habitual de les biblioteques WebRTC de C++ natives, Pion és una implementació nativa de Golang de WebRTC amb un millor rendiment, integració Go i control de versions dels protocols WebRTC.

    La biblioteca també permet la transmissió en temps real amb una gran quantitat d'integracions excel·lents amb una latència inferior al segon. Té la seva pròpia implementació de STUN, DTLS, SCTP, etc. i alguns experiments amb QUIC i WebAssembly. Aquesta biblioteca de codi obert en si és un bon recurs d'aprenentatge amb una documentació excel·lent, implementacions de protocols de xarxa i exemples fantàstics.

    La comunitat de Pion, liderada per un creador molt apassionat, és força animada, amb moltes discussions de qualitat sobre WebRTC. Si estàs interessat en aquesta tecnologia, uneix-te http://pion.ly/slack - aprendràs moltes coses noves.

    Escrivint CloudRetro a Golang

    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Implantació d'un treballador a Go

    Go Channels en acció

    Gràcies al bonic disseny del canal de Go, els problemes de transmissió d'esdeveniments i concurrència es simplifiquen molt. Com al diagrama, diferents GoRoutines tenen diversos components que funcionen en paral·lel. Cada component gestiona el seu estat i es comunica a través de canals. L'afirmació selectiva de Golang obliga a processar un esdeveniment atòmic cada vegada al joc (tic del joc). Això significa que no cal cap bloqueig per a aquest disseny. Per exemple, quan un usuari guarda, cal una instantània completa de l'estat del joc. Aquest estat hauria de romandre continu, iniciant sessió fins que es completi el desat. Durant cada marca de joc, el backend només pot gestionar una operació de desat o d'entrada, fent que el fil del procés sigui segur.

    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

    Aquesta plantilla de Golang s'adapta perfectament al meu cas d'ús CrowdPlay i Multiple Player. Seguint aquest patró, totes les entrades d'usuari d'una habitació s'incorporen al canal d'entrada central. Aleshores, els mitjans de joc es desplegaran a tots els usuaris de la mateixa sala. D'aquesta manera, aconseguim la divisió de l'estat del joc entre diverses sessions de joc de diferents usuaris.

    Jocs al núvol de codi obert a WebRTC: p2p, multijugador, latència zero
    Sincronització entre diferents sessions

    Desavantatges de Golang

    Golang no és perfecte. El canal és lent. En comparació amb el bloqueig, el canal Go és simplement una manera més fàcil de gestionar els esdeveniments concurrents i connectats, però el canal no ofereix el millor rendiment. Hi ha una lògica de bloqueig complexa sota el canal. Així que vaig fer alguns ajustos a la implementació, tornant a aplicar bloquejos i valors atòmics en substituir canals per optimitzar el rendiment.

    A més, el col·lector d'escombraries de Golang no està gestionat, cosa que de vegades provoca pauses sospitosament llargues. Això interfereix molt amb l'aplicació de transmissió en temps real.

    COG

    El projecte utilitza la biblioteca existent de codi obert Golang VP8/H264 per a la compressió de mitjans i Libretro per a emuladors de jocs. Totes aquestes biblioteques són simplement embolcalls de la biblioteca C a Go using COG. Alguns dels inconvenients s'enumeren a aquesta publicació de Dave Cheney. Problemes que he trobat:

    • incapacitat per detectar un accident a CGO, fins i tot amb Golang RecoveryCrash;
    • no identificar els colls d'ampolla de rendiment quan no podem detectar problemes detallats a CGO.

    Conclusió

    Vaig aconseguir el meu objectiu d'entendre els serveis de jocs al núvol i crear una plataforma que m'ajudi a jugar a jocs retro nostàlgics amb els meus amics en línia. Aquest projecte no hauria estat possible sense la biblioteca Pion i el suport de la comunitat Pion. Estic molt agraït pel seu intens desenvolupament. Les senzilles API proporcionades per WebRTC i Pion van garantir una integració perfecta. La meva primera prova de concepte es va publicar aquella mateixa setmana, tot i que no tenia coneixements previs de comunicació entre iguals (P2P).

    Malgrat la facilitat d'integració, el streaming P2P és realment una àrea molt complexa en informàtica. Ha de fer front a la complexitat de les arquitectures de xarxa de llarga data, com ara IP i NAT, per crear una sessió peer-to-peer. Mentre treballava en aquest projecte, vaig obtenir molts coneixements valuosos sobre les xarxes i l'optimització del rendiment, així que animo a tothom a provar de crear productes P2P amb WebRTC.

    CloudRetro s'adapta a tots els casos d'ús que esperava des de la meva perspectiva com a jugador retro. Tanmateix, crec que hi ha moltes àrees del projecte que puc millorar, com ara fer que la xarxa sigui més fiable i amb més rendiment, proporcionar gràfics de jocs de major qualitat o la possibilitat de compartir jocs entre usuaris. Estic treballant dur en això. Si us plau, seguiu projecte i recolzeu-lo si us agrada.

Font: www.habr.com

Afegeix comentari