Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero

Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
Software como servizo, infraestrutura como servizo, plataforma como servizo, plataforma de comunicación como servizo, videoconferencia como servizo, que pasa cos xogos na nube como servizo? Xa houbo varios intentos de crear xogos na nube (Cloud Gaming), como Stadia, lanzado recentemente por Google. Stadia non é novo en WebRTC, pero outros poden usar WebRTC do mesmo xeito?

Thanh Nguyen decidiu probar esta oportunidade no seu proxecto de código aberto CloudRetro. CloudRetro está baseado en Pion, popular Biblioteca WebRTC baseada en Go (grazas Amosado do equipo de desenvolvemento de Pion pola súa axuda na preparación deste artigo). Neste artigo, Thanh ofrece unha visión xeral da arquitectura do seu proxecto, e tamén fala de que cousas útiles aprendeu e que desafíos atopou durante o seu traballo.

Entrada

O ano pasado, cando Google anunciou Stadia, deixoume alucinado. A idea é tan única e innovadora que constantemente me preguntaba como era posible iso coa tecnoloxía existente. O desexo de comprender mellor este tema levoume a crear a miña propia versión dun xogo na nube de código aberto. O resultado foi simplemente fantástico. A continuación gustaríame compartir o proceso de traballo no meu ano proxecto.

TLDR: versión de diapositivas curtas con destacados

Por que os xogos na nube son o futuro

Creo que Cloud Gaming pronto se converterá na próxima xeración non só de xogos, senón tamén doutras áreas da informática. Os xogos na nube son o cumio do modelo cliente/servidor. Este modelo maximiza a xestión do backend e minimiza o traballo de frontend ao hospedar a lóxica do xogo nun servidor remoto e transmitir imaxes/audio ao cliente. O servidor realiza o procesamento pesado para que o cliente xa non estea a mercé das limitacións de hardware.

Google Stadia esencialmente permíteche xogar Xogos AAA (é dicir, xogos de gran éxito) nunha interface como YouTube. A mesma metodoloxía pódese aplicar a outras aplicacións pesadas fóra de liña como sistemas operativos ou deseño gráfico 2D/3D, etc. para que poidamos executalos de forma consistente en dispositivos con especificacións baixas en varias plataformas.

Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
O futuro desta tecnoloxía: Imaxina se Microsoft Windows 10 funcionase no navegador Chrome?

Os xogos na nube son un reto tecnicamente

Os xogos son unha desas áreas raras nas que se require unha resposta rápida e constante do usuario. Se ocasionalmente atopamos un atraso de 2 segundos ao facer clic nunha páxina, isto é aceptable. As emisións de vídeo en directo tenden a retrasarse uns segundos, pero aínda ofrecen unha usabilidade razoable. Non obstante, se o xogo se atrasa con frecuencia 500 ms, simplemente non se pode xogar. O noso obxectivo é conseguir unha latencia extremadamente baixa para que a diferenza entre a entrada e os medios sexa o menor posible. Polo tanto, o enfoque tradicional da transmisión de vídeo non é aplicable aquí.

Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
Modelo de xogo en nube xeral

Proxecto de código aberto CloudRetro

Decidín crear unha mostra de proba dun xogo na nube para ver se todo isto era posible cunhas restricións de rede tan estreitas. Elixín Golang para a proba de concepto porque era a linguaxe coa que estaba máis familiarizado e era moi adecuada para esta implementación por moitas outras razóns, como descubrín máis tarde. Go é sinxelo e desenvólvese moi rápido; As canles en Go son excelentes para xestionar o multiproceso.

Proxecto CloudRetro.io é un servizo de xogos na nube de código aberto para xogos retro. O obxectivo do proxecto é achegar a experiencia de xogo máis cómoda aos xogos retro tradicionais e engadir o modo multixogador.
Podes saber máis sobre o proxecto aquí: https://github.com/giongto35/cloud-game.

Funcionalidade CloudRetro

CloudRetro usa xogos retro para demostrar o poder dos xogos na nube. O que che permite gozar de moitas experiencias de xogo únicas.

  • Portabilidade do xogo
    • Reprodución instantánea ao abrir a páxina; non se necesita descarga nin instalación
    • Funciona nun navegador móbil, polo que non se necesita ningún software para executalo

  • As sesións de xogo pódense compartir en varios dispositivos e almacenarse na nube para a próxima vez que inicie sesión
  • O xogo pódese transmitir en streaming ou pode ser xogado por varios usuarios á vez:
    • Crowdplay como TwitchPlayPokemon, só máis multiplataforma e máis en tempo real
    • Xogos en liña sen conexión. Moitos usuarios poden xogar sen configurar unha rede. Samurai Shodown agora pode ser xogado por 2 xogadores a través da rede CloudRetro

    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Versión de demostración do xogo multixogador en liña en diferentes dispositivos

    A Infraestrutura

    Requisitos e pila tecnolóxica

    A continuación móstrase unha lista de requisitos que fixen antes de comezar o proxecto.

    1. Un xogador
    Este requisito pode non parecer demasiado importante ou obvio aquí, pero é unha das miñas principais conclusións: permite que os xogos na nube estean o máis lonxe posible dos servizos de transmisión tradicionais. Se nos centramos nun xogo para un só xogador, podemos desfacernos dun servidor centralizado ou CDN porque non temos que transmitir para as masas. En lugar de cargar fluxos a un servidor receptor ou pasar paquetes a un servidor WebSocket centralizado, os fluxos de servizo entréganse directamente ao usuario mediante unha conexión WebRTC punto a punto.

    2. Fluxo multimedia de baixa latencia
    Ao ler sobre Stadia, adoito ver que WebRTC se menciona nalgúns artigos. Decateime de que WebRTC é unha tecnoloxía excelente e é perfecta para usar en xogos na nube. WebRTC é un proxecto que proporciona aos navegadores web e aplicacións móbiles comunicación en tempo real a través dunha sinxela API. Ofrece conectividade peer-to-peer, está optimizado para medios e ten códecs estándar integrados como VP8 e H264.

    Priorizo ​​garantir a mellor experiencia de usuario posible sobre o mantemento de gráficos de alta calidade. Algunhas perdas son aceptables no algoritmo. Google Stadia ten un paso adicional para reducir o tamaño da imaxe no servidor e os fotogramas realízanse a unha calidade superior antes de transmitirse aos seus compañeiros.

    3. Infraestrutura distribuída con trazado xeográfico
    Por moi optimizados que estean o algoritmo de compresión e o código, a rede segue sendo o factor decisivo que máis contribúe á latencia. A arquitectura debe ter un mecanismo para emparellar o servidor máis próximo ao usuario para reducir o tempo de ida e volta (RTT). A arquitectura debe ter 1 coordinador e varios servidores de streaming distribuídos por todo o mundo: EE. UU. Oeste, EE. UU. Leste, Europa, Singapur, China. Todos os servidores de streaming deben estar completamente illados. O sistema pode axustar a súa distribución cando un servidor se une ou abandona a rede. Así, con gran tráfico, engadir servidores adicionais permite a escala horizontal.

    4. Compatibilidade do navegador
    Os xogos na nube están no seu mellor momento cando menos requiren dos usuarios. Isto significa que é posible executalo nun navegador. Os navegadores axudan a que a experiencia de xogo sexa o máis cómoda posible para os usuarios, aforrándoos de instalar software e hardware. Os navegadores tamén axudan a proporcionar funcionalidade multiplataforma entre as versións para móbiles e de escritorio. Afortunadamente, WebRTC é compatible con varios navegadores.

    5. Separación clara da interface do xogo e do servizo
    Vexo o servizo de xogos na nube como unha plataforma. Todo o mundo debería poder conectar calquera cousa á plataforma. Agora integrei LibRetro con servizo de xogos na nube porque LibRetro ofrece unha fermosa interface de emulador de xogos para xogos retro como SNES, GBA, PS.

    6. Salas para multixogador, xogo en multitude e conexión externa (ligazón profunda) co xogo
    CloudRetro admite moitas novas partidas como CrowdPlay e Online Multiplayer para xogos retro. Se varios usuarios abren a mesma ligazón profunda en ordenadores diferentes, verán o mesmo xogo en execución e mesmo poderán unirse a el.

    Ademais, os estados do xogo almacénanse no almacenamento na nube. Isto permite aos usuarios seguir xogando en calquera momento en calquera outro dispositivo.

    7. Escalado horizontal
    Como calquera SAAS hoxe en día, os xogos na nube deben estar deseñados para ser escalables horizontalmente. O deseño de coordinador-traballador permítelle engadir máis traballadores para atender máis tráfico.

    8. Sen conexión a unha nube
    A infraestrutura de CloudRetro está aloxada en diferentes provedores de nube (Digital Ocean, Alibaba, provedor personalizado) para diferentes rexións. Active a execución nun contenedor Docker para a infraestrutura e configuro a configuración da rede mediante un script bash para evitar estar bloqueado nun único provedor de nube. Ao combinar isto con NAT Traversal en WebRTC, podemos ter a flexibilidade de implementar CloudRetro en calquera plataforma na nube e mesmo en máquinas de calquera usuario.

    Deseño arquitectónico

    Traballador: (ou o servidor de streaming mencionado anteriormente) multiplica os xogos, executa a canalización de codificación e transmite os medios codificados aos usuarios. As instancias dos traballadores distribúense por todo o mundo e cada traballador pode xestionar varias sesións de usuarios simultaneamente.

    Coordinador: encárgase de emparellar o novo usuario co traballador máis axeitado para o streaming. O coordinador interactúa cos traballadores a través de WebSocket.

    Almacenamento do estado do xogo: almacenamento remoto central para todos os estados do xogo. Este almacenamento ofrece funcións importantes como gardar/cargar a distancia.

    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Arquitectura de nivel superior de CloudRetro

    Script personalizado

    Cando un novo usuario abre CloudRetro nos pasos 1 e 2 que se mostran na figura seguinte, o coordinador xunto coa lista de traballadores dispoñibles pídese na primeira páxina. Despois diso, no paso 3 o cliente calcula os atrasos para todos os candidatos mediante unha solicitude de ping HTTP. A continuación, esta lista de atrasos envíase de novo ao coordinador para que determine o traballador máis axeitado para atender ao usuario. O paso 4 a continuación crea o xogo. Establécese unha conexión de streaming WebRTC entre o usuario e o traballador asignado.
    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Script de usuario despois de ter acceso

    O que hai dentro do traballador

    As canalizacións de xogos e de streaming almacénanse dentro do traballador de forma illada e intercambian información alí a través da interface. Actualmente, esta comunicación realízase mediante a transferencia de datos na memoria vía Canles de Golang no mesmo proceso. O seguinte obxectivo é a segregación, é dicir. lanzamento independente do xogo noutro proceso.

    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Interacción dos compoñentes dos traballadores

    Compoñentes principais:

    • WebRTC: un compoñente cliente que acepta entradas do usuario e produce medios codificados desde o servidor.
    • Emulador de xogos: compoñente de xogo. Grazas á biblioteca Libretro, o sistema pode executar o xogo dentro do mesmo proceso e interceptar internamente medios e fluxo de entrada.
    • Os fotogramas do xogo son capturados e enviados ao codificador.
    • Codificador de imaxe/audio: unha canalización de codificación que toma fotogramas multimedia, codificaos en segundo plano e emite imaxes/audio codificados.

    Implantación

    CloudRetro confía en WebRTC como tecnoloxía principal, polo que antes de mergullarme nos detalles da implementación de Golang, decidín falar do propio WebRTC. Esta é unha tecnoloxía incrible que me axudou moito a conseguir unha latencia inferior a segundos para transmitir datos.

    WebRTC

    WebRTC está deseñado para ofrecer conexións punto a punto de alta calidade en aplicacións móbiles e navegadores nativos mediante API simples.

    Travesía NAT

    WebRTC é coñecido pola súa funcionalidade NAT Traversal. WebRTC está deseñado para a comunicación peer-to-peer. O seu obxectivo é atopar a ruta directa máis axeitada, evitando pasarelas NAT e cortalumes para a comunicación peer-to-peer mediante un proceso denominado ICE. Como parte deste proceso, as API de WebRTC atopan o seu enderezo IP público usando servidores STUN e reenvíano ao servidor de retransmisión (XIRAR) cando non se poida establecer unha conexión directa.

    Non obstante, CloudRetro non explota plenamente esta función. As súas conexións peer-to-peer non existen entre usuarios, senón entre usuarios e servidores na nube. O lado do servidor do modelo ten menos restricións de comunicación directa que un dispositivo de usuario típico. Isto permítelle abrir previamente os portos de entrada ou usar directamente enderezos IP públicos, xa que o servidor non está detrás de NAT.

    Anteriormente, quería converter o proxecto nunha plataforma de distribución de xogos para Cloud Gaming. A idea era permitir aos creadores de xogos proporcionar xogos e recursos de streaming. E os usuarios interactuarían directamente cos provedores. Deste xeito descentralizado, CloudRetro é só un marco para conectar recursos de streaming de terceiros aos usuarios, o que o fai máis escalable cando xa non está aloxado. O papel de WebRTC NAT Traversal aquí é moi importante para facilitar a inicialización da conexión peer-to-peer en recursos de streaming de terceiros, facilitando que o creador se conecte á rede.

    Compresión de vídeo

    A compresión de vídeo é unha parte indispensable da canalización e contribúe en gran medida a un fluxo suave. Aínda que non é necesario coñecer todos os detalles da codificación de vídeo VP8/H264, comprender os conceptos pode axudarche a comprender as opcións de velocidade de transmisión de vídeo, a depurar comportamentos inesperados e a axustar a latencia.

    Comprimir vídeo para un servizo de streaming é un reto porque o algoritmo debe garantir que o tempo total de codificación + tempo de transmisión da rede + tempo de decodificación sexa o menor posible. Ademais, o proceso de codificación debe ser coherente e continuo. Algunhas compensacións de codificación non se aplican; por exemplo, non podemos favorecer tempos de codificación longos fronte a tamaños de ficheiros e tempos de decodificación máis pequenos, nin usar compresión inconsistente.

    A idea detrás da compresión de vídeo é eliminar bits de información innecesarios mantendo un nivel aceptable de precisión para os usuarios. Ademais de codificar cadros de imaxes estáticas individuais, o algoritmo deduce o cadro actual dos anteriores e os seguintes, polo que só se envía a súa diferenza. Como se pode ver no exemplo de Pacman, só se transmiten puntos diferenciais.

    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Comparación de cadros de vídeo usando Pacman como exemplo

    Compresión de audio

    Así mesmo, o algoritmo de compresión de audio omite datos que non poden ser percibidos polos humanos. Opus é actualmente o códec de audio con mellor rendemento. Está deseñado para transmitir unha onda de audio a través dun protocolo de datagrama ordenado como RTP (Protocolo de transporte en tempo real). A súa latencia é menor que mp3 e aac, e a calidade é maior. A latencia adoita ser de 5 ~ 66,5 ms.

    Pion, WebRTC en Golang

    Peón é un proxecto de código aberto que trae WebRTC a Golang. En lugar do envoltorio habitual das bibliotecas C++ WebRTC nativas, Pion é unha implementación nativa de Golang de WebRTC con mellor rendemento, integración de Go e control de versións nos protocolos WebRTC.

    A biblioteca tamén permite a transmisión con moitos excelentes incorporados cunha latencia inferior a un segundo. Ten a súa propia implementación de STUN, DTLS, SCTP, etc. e algúns experimentos con QUIC e WebAssembly. Esta biblioteca de código aberto en si é un recurso de aprendizaxe moi bo con excelente documentación, implementacións de protocolos de rede e exemplos interesantes.

    A comunidade de Pion, dirixida por un creador moi apaixonado, é bastante animada, con moitas discusións de calidade sobre WebRTC. Se estás interesado nesta tecnoloxía, únete http://pion.ly/slack - aprenderás moitas cousas novas.

    Escribindo CloudRetro en Golang

    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Implantación dun traballador en Go

    Go Channels en acción

    Grazas ao fermoso deseño da canle de Go, os problemas de transmisión de eventos e concorrencia simplifícanse moito. Como no diagrama, diferentes GoRoutines teñen varios compoñentes que funcionan en paralelo. Cada compoñente xestiona o seu estado e comunícase a través de canles. A afirmación selectiva de Golang obriga a procesar un evento atómico cada vez no xogo (tick do xogo). Isto significa que non se necesita bloqueo para este deseño. Por exemplo, cando un usuario garda, é necesaria unha instantánea completa do estado do xogo. Este estado debe permanecer continuo, iniciando sesión ata que se complete o gardado. Durante cada marca de xogo, o backend só pode xestionar unha operación de gardado ou entrada, facendo que o fío do proceso sexa seguro.

    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

    Este modelo de Golang encaixa perfectamente co meu caso de uso de CrowdPlay e Multiple Player. Seguindo este patrón, todas as entradas do usuario nunha sala están integradas na canle de entrada central. A continuación, os medios de xogo despréganse a todos os usuarios da mesma sala. Deste xeito, conseguimos a división do estado de xogo entre varias sesións de xogo de diferentes usuarios.

    Xogos na nube de código aberto en WebRTC: p2p, multixogador, latencia cero
    Sincronización entre diferentes sesións

    Desvantaxes de Golang

    Golang non é perfecto. A canle é lenta. En comparación co bloqueo, a canle Go é simplemente un xeito máis sinxelo de xestionar eventos simultáneos e en liña, pero a canle non ofrece o mellor rendemento. Hai unha complexa lóxica de bloqueo debaixo da canle. Así que fixen algúns axustes na implementación, volvendo a aplicar bloqueos e valores atómicos ao substituír as canles para optimizar o rendemento.

    Ademais, o colector de lixo en Golang non está xestionado, o que ás veces provoca pausas sospeitosamente longas. Isto interfire moito coa aplicación de transmisión en tempo real.

    COG

    O proxecto usa a biblioteca Golang VP8/H264 de código aberto existente para a compresión multimedia e Libretro para emuladores de xogos. Todas estas bibliotecas son simplemente envoltorios da biblioteca C en Go using COG. Algunhas das desvantaxes están listadas en esta publicación de Dave Cheney. Problemas que atopei:

    • incapacidade para detectar un accidente en CGO, mesmo con Golang RecoveryCrash;
    • falla para identificar os pescozos de botella de rendemento cando non somos capaces de detectar problemas detallados en CGO.

    Conclusión

    Conseguín o meu obxectivo de comprender os servizos de xogos na nube e crear unha plataforma que me axude a xogar nostálxicos xogos retro cos meus amigos en liña. Este proxecto non sería posible sen a biblioteca Pion e o apoio da comunidade Pion. Estou moi agradecido polo seu intenso desenvolvemento. As sinxelas API proporcionadas por WebRTC e Pion aseguraron unha integración perfecta. A miña primeira proba de concepto publicouse esa mesma semana, aínda que non tiña coñecementos previos de comunicación entre pares (P2P).

    A pesar da facilidade de integración, a transmisión P2P é unha área moi complexa na informática. Ten que lidiar coa complexidade das arquitecturas de rede de longa data, como IP e NAT, para crear unha sesión peer-to-peer. Mentres traballaba neste proxecto, aprendín moitos coñecementos valiosos sobre redes e optimización do rendemento, polo que animo a todos a que intenten construír produtos P2P usando WebRTC.

    CloudRetro atende a todos os casos de uso que esperaba desde a miña perspectiva como xogador retro. Non obstante, creo que hai moitas áreas do proxecto que podo mellorar, como facer que a rede sexa máis fiable e eficiente, ofrecer gráficos de xogos de maior calidade ou a posibilidade de compartir xogos entre usuarios. Estou traballando duro nisto. Por favor, siga proxecto e apoialo se che gusta.

Fonte: www.habr.com

Engadir un comentario