Visão geral da infraestrutura de jogos em nuvem

Esta solução apresenta uma visão geral dos componentes e padrões de projeto de software comuns usados para hospedar infraestruturas de jogos em plataformas de nuvem.

Os videogames evoluíram ao longo das últimas décadas e se tornaram um ramo de negócios de entretenimento lucrativo. Com a disseminação da Internet banda-larga, um dos principais fatores no crescimento dos jogos foi a possibilidade de curti-los on-line.

Os jogos on-line são apresentados de diversas maneiras, como partidas multijogadores, mundos virtuais com vários personagens e experiências de um jogador só.

Antigamente, os jogos usavam um modelo de servidor cliente que exigia a compra e manutenção de servidores dedicados no local ou colocalizados para executar a infraestrutura on-line. Somente grandes estúdios e editoras podiam arcar com esses custos. Além disso, era necessário realizar projeções extensas e planejamento de recursos para atender às demandas dos clientes sem exceder os gastos com hardware fixo. Com os recursos atuais de computação baseados em nuvem, os desenvolvedores e editores de jogos de todos os portes podem solicitar e receber qualquer recurso sob demanda. Isso evita gastos iniciais excessivos e as ameaças de provisionamento de hardware inferior ou superior ao necessário.

Componentes de alto nível

O diagrama a seguir ilustra a porção on-line de uma arquitetura de jogos.

Diagrama de infraestrutura de jogos no GCP com componentes de front-end e back-end.

Os componentes de front-end da arquitetura de jogos incluem:

  • serviços de plataforma de jogos que fornecem funcionalidades além do jogo;
  • servidores de dedicados que hospedam o jogo.

Os componentes de back-end da arquitetura de jogos incluem:

  • o estado de jogo, permanente no sistema de registros e tipicamente armazenado no banco de dados do jogo;
  • a pilha de análise que armazena e consulta eventos de análises e jogabilidade.

Esses componentes podem ser hospedados em diversos ambientes: no local, em nuvem privada ou pública ou em uma solução totalmente gerenciada. Desde que os sistemas atendam aos requisitos de latência para comunicação entre os componentes e os usuários finais, qualquer uma dessas opções pode funcionar.

Front-end

O front-end fornece interfaces para os clientes interagirem, seja diretamente ou por meio de um balanceador de carga.

Por exemplo, o front-end de um jogo de tiro em primeira pessoa baseado em partidas, no geral, inclui um serviço de combinação. Esse serviço distribui aos clientes de jogos informações de conexão das instâncias de servidores de jogos dedicadas:

  1. Um cliente envia uma solicitação para o serviço de combinação.
  2. O serviço de combinação envia informações de conexão ao cliente.
  3. O cliente pode, então se conectar diretamente à instância de servidor de jogos dedicada usando o User Datagram Protocol (UDP).

Os serviços de front-end não precisam ser usados exclusivamente por clientes externos. É comum que eles se comuniquem entre si e com o back-end.

No entanto, por estarem disponíveis na Internet, eles podem estar mais expostos a ataques. Proteja seu serviço de front-end contra ataques de negação de serviço e pacotes malformados para ajudar a resolver as preocupações com segurança e confiabilidade. Em comparação, serviços de back-end, geralmente, só podem ser acessados usando código confiável, e são, portanto, mais difíceis de atacar.

Serviços de plataforma de jogos

Este componente é comumente chamado de serviços de plataforma ou serviços on-line. Os serviços de plataforma fornecem interfaces para as funções essenciais dos jogos, como permitir que os jogadores façam parte da mesma instância de servidor de jogo dedicada e manter o gráfico social de "lista de amigos" do jogo. Esses serviços costumam ser oferecidos pela plataforma em que o jogo é executado, como Steam, Xbox Live ou Google Play Games:

  • Quadro de classificação e histórico de partidas
  • combinações
  • lobby on-line
  • bate-papo
  • gerenciamento de inventário
  • autorização
  • Grupo/time
  • Perfil
  • Clã
  • Desbloqueio em várias plataformas
  • Feeds
  • Mapeamento de identidade social
  • Análise de dados
  • Presença

Os serviços de plataforma de jogos evoluíram de forma parecida com os serviços da Web:

  • No início dos anos 2000, um pacote típico de serviços de plataforma era executado como serviço monolítico, frequentemente implementado como um singleton. Mesmo quando federado, este padrão não é recomendado para implementações de nuvem.

  • O novo padrão de arquitetura orientada a serviços (SOA, na sigla em inglês) tornou-se conhecido em meados dos anos 2000, conforme o setor alterava diversos serviços para se tornar escalável de modo independente. Além disso, os serviços agora podem ser acessados não apenas por clientes e servidores de jogos, mas também por serviços Web e, por fim, por apps de smartphones.

  • Nos últimos anos, muitos desenvolvedores adotaram a abordagem de microsserviços, defendida por empresas Web de rápido crescimento. Muitos dos principais desafios dos serviços de plataforma e aplicativos Web são iguais, tais como ativar ciclos rápidos de desenvolvimento e executar serviços altamente distribuídos em todo o mundo. Os microsserviços podem ser uma excelente opção ao desenvolver aplicativos que serão executados em plataformas de nuvem.

  • Além disso, agora há muitos serviços hospedados ou gerenciados que fornecem uma maneira de desenvolver serviços de plataforma ou serviços de plataforma totalmente gerenciados.

Serviços de plataforma de back-end

Muitos serviços de plataforma são acessados por clientes externos, mas às vezes é interessante que o serviço seja acessado somente por outras porções da sua infraestrutura on-line, como, por exemplo, um serviço de ranking de jogadores confidencial. Normalmente, os serviços de plataforma de back-end não têm roteamento de rede externa e endereço IP, mas costumam seguir as mesmas práticas de projeto dos serviços de plataforma de front-end.

Soluções de serviços de plataforma do Google Cloud Platform

As soluções a seguir fornecem mais informações sobre como desenvolver serviços de back-end no Cloud Platform.

Servidor de jogos dedicado

Os servidores de jogos dedicados apresentam a lógica do jogo. Para minimizar a latência percebida pelo usuário, os aplicativos de jogos dos clientes normalmente se comunicam diretamente com os servidores. Isso os torna parte da arquitetura de serviços de front-end.

Como o setor não tem uma terminologia padrão, considere as definições a seguir para os fins deste artigo:

  • Máquina refere-se à máquina física ou virtual em que os processos do servidor de jogos são executados.
  • Servidor de jogos refere-se ao processo do servidor de jogos. Vários processos de servidor de jogos podem ser executados simultaneamente em uma máquina.
  • instância refere-se a um único processo de servidor de jogos.

Tipos de servidores de jogos dedicados

O termo dedicado pode ser entendido errado no contexto atual dos servidores de jogo de back-end. Originalmente, dedicado referia-se aos servidores de jogos que eram executados em um hardware dedicado, em uma proporção 1:1. Hoje em dia, a maioria dos editores de jogos gerenciam diversos processos de servidores de jogos que são executados simultaneamente na mesma máquina. Agora, os processos raramente contam com máquinas inteiras dedicadas a eles, mas o termo servidor de jogos dedicado ainda é frequentemente usado no setor.

Os servidores de jogos dedicados são tão variados quanto os tipos de jogos que eles executam. Algumas categorias de servidores de jogos de alto nível serão discutidas na próxima seção.

Simulações em tempo real

Até recentemente, quase todos os servidores de jogos dedicados de um produto enviado comercialmente faziam parte do front-end nos jogos de simulação em tempo real. Os servidores desse tipo de jogo, historicamente, atingiram os limites de escalonamento vertical. Os jogos mais exigentes migraram para táticas manuais de escalonamento horizontal como executar processos de vários servidores por máquina ou fragmentação geográfica pelo mundo. A comunicação UDP com controle de fluxo personalizado, confiabilidade e impedimento de congestionamento é o paradigma de rede dominante.

A maioria dos servidores de jogos de simulação em tempo real é implementada em um loop sem fim, em que o objetivo é finalizar o loop dentro de um determinado período. Os intervalos de tempo comuns são de 16 ou 33 milissegundos, o que resulta em uma taxa de atualização de status de 60 ou 30 vezes por segundo, respectivamente. A taxa de atualização é também referida como frame rate ou tick rate. O servidor atualiza a simulação com uma frequência alta, mas não é incomum que ele comunique as atualizações de estado para os clientes somente após diversas atualizações. Isso mantém os requisitos de largura de banda de rede em uma taxa razoável. Os efeitos da atualização menos frequente podem ser atenuados com estratégias como compensação de atraso, interpolação e extrapolação.

Tudo isso significa que os servidores de jogos de simulação em tempo real executam cargas de trabalho sensíveis, do ponto de vista da latência, e intensas, do ponto de vista da largura de banda e da computação. Isso requer uma escolha cuidadosa do projeto do servidor de jogos e das plataformas de computação em que eles serão executados.

Jogos baseados em sessões ou partidas

Os jogos em que os servidores são projetados para executar sessões específicas são muito comuns hoje em dia. Exemplos clássicos são as partidas de multijogadores com atiradores em primeira pessoa (FPS, na sigla em inglês) como Call of Duty™, Overwatch™ ou Titanfall™. Há também os jogos no estilo arena de batalha on-line para multijogadores (MOBA, na sigla em inglês) como Dota 2™ e Vainglory™. Esses jogos contam com servidores que requerem jogabilidade rápida e cálculos de estado de jogo detalhados, frequentemente com threads devotados a inteligência artificial ou simulação física.

Mundos persistentes massivos para multijogadores

Quase duas décadas atrás, com o Ultima Online™, o caminho foi aberto para uma grande proliferação de jogos do tipo on-line massivo para multijogadores (MMO, na sigla em inglês). Atualmente, a maioria dos MMOs famosos como World of Warcraft™ e Guild Wars™ é caracterizada por projetos de servidores complexos com um conjunto de recursos em constante evolução.

O ocorrência de problemas complexos é comum em servidores de jogos MMO, como a transmissão de entidades de jogos entre instâncias do servidor, fragmentação ou sincronização do mundo do jogo e colocalização física das instâncias, simulando áreas adjacentes do mundo do jogo. Os requisitos de computação e memória para calcular as atualizações de estado de um mundo persistente que contém centenas ou milhares de jogadores podem levar a soluções como a dilatação do tempo em Eve Online™.

Servidores baseados em solicitação/resposta

Tecnicamente, todos os servidores de jogos dedicados são baseados em uma série de solicitações e respostas. No entanto, os servidores de jogos para dispositivos móveis, que não têm uma demanda crítica por comunicação em tempo real, adotaram a semântica de solicitação e resposta de HTTP como a usada em hospedagem na Web.

Os desafios para os servidores de jogos de solicitação/resposta são os mesmos que os enfrentados por qualquer serviço da Web, incluindo:

  • Manter o tempo de resposta do servidor de jogos o mais rápido possível.
  • Distribuir globalmente os servidores de jogos para reduzir a latência e adicionar redundância.
  • Validar as ações dos clientes de jogos no servidor para proteção contra explorações ou trapaças.
  • Proteger os servidores de jogos contra negação de serviço e outros ataques.
  • Implementar atrasos exponenciais para novas tentativas de comunicação no lado do cliente.
  • Criar sessões "permanentes" ou externalizar o estado do processo.

Os pontos positivos dos servidores de jogos de solicitação/resposta, como semântica de comunicação compacta e facilidade de novas tentativas após falha no aplicativo ou na rede, funcionam bem para jogos para dispositivos móveis baseados em turnos.

Como externalizar o estado do mundo do jogo

Cada vez mais os jogadores esperam não enfrentar tempo de inatividade nos jogos. Isso significa que você precisa proteger a experiência dos jogadores contra os problemas que afetam instâncias individuais de servidor. Para isso, um jogo deve manter o estado do jogador fora de um processo de servidor de jogo único. As vantagens são muitas, como resiliência contra falhas nos processos do servidor e a possibilidade de haver balanceamento de carga efetivo.

Infelizmente, utilizar apenas os padrões de estado externalizados comuns nos serviços da Web pode causar problemas por diversos motivos, incluindo:

  • A velocidade na qual as atualizações são escritas para um estado externo pode ser um desafio quando há várias entidades únicas atualizando dezenas de vezes por segundo. Isso ocorre mesmo se você usar o armazenamento de chave-valor em cache de memória, como Memcached ou Redis.
  • A latência tail-end de consultas de caches de estado externo representa um grande problema. É difícil atender aos prazos de atualização de estado se 1%, ou até mesmo 0,1%, das suas consultas tiverem latência ou uma ordem de magnitude maior que o prazo de atualização.
  • Determinar quais processos têm autoridade somente de leitura ou de leitura e gravação sobre os objetos em armazenamento em cache de estado externo introduz complexidades no modelo do servidor.

No entanto, resolver esses problemas traz diversos efeitos colaterais benéficos. Um estado externalizado com sucesso que esteja disponível para vários processos com acesso de gerenciamento adequado pode simplificar muito a capacidade de calcular porções da atualização do estado de jogo em paralelo. As vantagens são semelhantes para a migração de entidades entre instâncias.

Soluções de servidor de jogos dedicado do Cloud Platform

Os artigos a seguir descrevem como executar servidores de jogos dedicados no Cloud Platform.

Back-end

Os serviços de back-end apresentam interfaces apenas para outros serviços de front-end e back-end. Clientes externos não podem se comunicar diretamente com um serviço de back-end. Normalmente, os serviços de back-end fornecem um maneira de armazenar e acessar dados, como os dados de estado do jogo em um banco de dados, ou de registrar eventos de análise em um armazém de dados.

Banco de dados para jogos

Entre os cenários que podem fazer com que os jogadores encerrem uma partida e desistam de jogar novamente estão servidores inoperantes e perda do progresso do jogador. Esses dois casos serão possíveis se você tiver uma camada de banco de dados projetada de maneira inadequada.

O banco de dados que hospeda o estado de mundo do jogo e os dados de progresso do jogador podem ser considerados os pontos mais críticos da sua infraestrutura de jogos.

Avalie a capacidade de os bancos de dados lidarem com as cargas de trabalho esperadas e com aquela exigida se o jogo se tornar um grande sucesso. Um back-end projetado e testado para a base de jogadores estimada, mas que repentinamente recebe uma solicitação de carga muito maior, provavelmente não será capaz de realizar os serviços com confiabilidade. Deixar de se planejar para um sucesso inesperado pode fazer com que seu jogo fracasse, porque muitos jogadores o abandonarão quando ele se tornar difícil de jogar por conta de problemas com o banco de dados.

Os jogos são particularmente vulneráveis a isso. A maioria das empresas com um produto bem-sucedido pode esperar um crescimento gradual e orgânico. Mas um jogo comum verá um grande pico de interesse inicial seguido por uma queda, chegando a uma quantidade de uso muito menor. Se o seu jogo for um sucesso, um banco de dados com muitas solicitações causará grandes atrasos antes de salvar o progresso do usuário, podendo, inclusive, falhar nesse processo. Ter que decidir quais recursos do jogo não vão mais ser compatíveis com atualizações em tempo real não é algo pelo qual os desenvolvedores de jogos querem passar. Por isso, planeje cuidadosamente seus recursos de banco de dados.

Ao desenvolver um banco de dados para jogos:

  • Tome uma decisão embasada. Não use um banco de dados durante o desenvolvimento por ser fácil de testar e depois passe a usá-lo como banco de dados de produção sem avaliar todas as opções. É importante entender o tipo e a frequência dos acessos do jogo ao banco de dados com a base esperada de jogadores e multiplicar essas estimativas por 10. Assim, você poderá tomar uma decisão mais embasada sobre qual back-end pode lidar melhor com esses cenários. Não se coloque em uma situação de tentar aprender como lidar com uma crise de banco de dados quando ela já aconteceu.
  • Não presuma que uma solução seja a correta. Não há uma regra que defina que você só pode usar um tipo de banco de dados. Muitos jogos de sucesso armazenam informações de conta e processam compras dentro do app usando um banco de dados relacional, enquanto mantêm as informações de estado do jogo em um banco de dados NoSQL separado. O banco de dados NoSQL é melhor para cargas de trabalho com baixa latência e grandes volumes, enquanto o banco de dados relacional oferece transações garantidas.
  • Faça backup dos dados. É importante fazer backups regulares e distribuídos geograficamente para possibilitar a recuperação em caso de falhas no banco de dados.

Bancos de dados relacionais

Muitas equipes de desenvolvimento de jogos começam com um único banco de dados relacional. Quando o volume de dados e o tráfego aumentam a um ponto em que o desempenho do banco de dados não é mais aceitável, a abordagem mais comum é escalonar o banco de dados. Quando o escalonamento não é mais viável, muitos desenvolvedores implementam uma camada de serviço de banco de dados personalizada. Nela, é possível priorizar resultados de cache e consultas, os quais limitam o acesso ao banco de dados. Adicionar o escalonamento e uma camada de serviço de banco de dados cria um back-end de jogos capaz de lidar com grandes números de jogadores, mas esses métodos podem apresentar alguns problemas comuns:

  • Escalonamento: os bancos de dados relacionais tradicionais têm uma abordagem de escalonamento vertical. No entanto, ao planejar um back-end de jogos nativo em nuvem, recomenda-se usar uma abordagem de escalonamento horizontal porque o número máximo de núcleos em uma única máquina virtual (VM, na sigla em inglês) é limitado. Em contrapartida, adicionar máquinas virtuais ao seu projeto na nuvem é bem simples. Os bancos de dados relacionais têm padrões para dimensionamento horizontal, como fragmentação, clusters e réplicas por níveis. No entanto, pode ser difícil usar esses métodos em um banco de dados em execução que não tenha períodos de inatividade. Se houver alguma chance de seu tráfego ou volume de dados ultrapassar a capacidade de um único banco de dados, comece com um cluster pequeno. Não deixe para aprender a escalonar o banco de dados quando a crise bater. Adicionar nós em um cluster enquanto ele está sendo executado não é simples, mas é possível.
  • Alterações de esquema: pouquíssimos jogos bem-sucedidos são lançados com um esquema de banco de dados que dura por todo o tempo de vida útil do jogo. Os jogadores demandam novos recursos e conteúdos, e essas adições requerem salvar novos tipos de dados. Determine no início do processo de desenvolvimento como você fará para atualizar seu esquema. Tentar atualizá-lo após o lançamento do jogo sem um processo estabelecido pode resultar em um tempo de inatividade inesperado ou até mesmo em perda de dados dos jogadores.
  • Administração: dimensionar um banco de dados relacional em execução e atualizar os esquemas dele são operações complexas. Os bancos de dados relacionais gerenciados automaticamente são serviços comuns nas plataformas de nuvem, mas a taxa de adoção deles por back-ends de jogos é baixa no momento. Isso se deve às grandes cargas de trabalho de gravação dos back-ends de jogos.

Bancos de dados NoSQL

Os bancos de dados não relacionais podem oferecer a solução para operar em escala, especialmente com grandes cargas de trabalho de gravação. No entanto, é preciso entender os modelos de dados, padrões de acesso e garantias transacionais NoSQL.

Há diversos tipos de bancos de dados NoSQL. Aqueles que funcionam bem para o armazenamento de estado de mundo de jogos têm os seguintes recursos:

  • Escalonamento: eles são projetados tendo em mente o escalonamento horizontal, e muitas vezes o utilizam por padrão. Geralmente, a operação de redimensionamento de clusters é feita sem tempo de inatividade, porém pode haver perda de desempenho até que os nodes adicionais sejam totalmente integrados.

  • Alterações de esquema: o esquema é dinâmico e aplicado pela camada do aplicativo. Essa é uma grande vantagem, já que adicionar um outro campo para um recurso novo do jogo pode ser muito simples.

  • Administração: a maioria dos fornecedores de nuvem oferecem pelo menos um mecanismo de armazenamento de dados NoSQL hospedado ou gerenciado, e o Google Cloud Platform oferece vários.

Soluções de banco de dados de jogos no Google Cloud Platform

Análise de dados

As análises se tornaram um importante componente dos jogos modernos. Tanto os clientes de jogos quanto os serviços on-line podem enviar análises e eventos de telemetria para um ponto de coleta comum, em que os eventos são armazenados em um banco de dados. Eles podem ser consultados por qualquer pessoa, de programadores e desenvolvedores de jogos a analistas de business intelligence e representantes de atendimento ao cliente. À medida que a complexidade das análises coletadas cresce, aumenta a necessidade de manter esses eventos em um formato que pode ser consultado de maneira fácil e rápida.

Na última década, cresceu a popularidade do Apache™ Hadoop®, uma biblioteca de código aberto baseada em trabalhos publicados pelo Google. Com a expansão do ecossistema Hadoop, o uso de operações de extração, transformação e carregamento (ETL, na sigla em inglês) em lotes complexos aumentou para formatar e inserir eventos de análise em um serviço de armazenamento de dados. O uso do MapReduce acelerou a taxa de envio dos resultados acionáveis, o que ajudou a ativar análises novas e de computação mais intensiva.

Ao mesmo isso, as tecnologias disponíveis na nuvem continuaram a evoluir. Muitas delas estão disponíveis como serviços gerenciados rápidos de aprender e não requerem equipes de operações dedicadas. Com o mais recente paradigma de streaming de ETL do Google, uma abordagem unificada de processamento em lote e stream é oferecida e está disponível tanto como serviço de nuvem gerenciado quanto como projeto de código aberto Apache Beam. As melhorias contínuas nos preços de armazenamento de dados na nuvem possibilitam manter enormes quantidades de registros e eventos de análise em bancos de dados de nuvem massivos e gerenciados que otimizam a maneira de ler e gravar os dados. Os mais recentes mecanismos de consulta para esses bancos de dados são capazes de agregar TBs de dados em segundos. Veja um exemplo de como analisar 50 bilhões de exibições de página da Wikipedia em 5 segundos.

Soluções de análises de jogos no Google Cloud Platform

A seguir

As soluções para jogos on-line seguem um padrão comum: os clientes interagem com um front-end de serviços e servidores de jogos, que se comunicam com um back-end de armazenamento de análises e estado. Esses componentes podem ser executados no local, na nuvem ou das duas maneiras. Para mais detalhes sobre padrões, consulte soluções para jogos.