Qual é a melhor arquitetura de servidor para jogos em tempo real?

10

Estou desenvolvendo um jogo em tempo real que deve conter milhares de jogadores em tempo real (FPS como. Max 1s lag). Qual seria a melhor infraestrutura para isso?

Minha idéia foi usar dois clusters de servidores - um para o servidor final (todo o lado da computação) e um para o banco de dados, onde um balanceador de carga é "responsável" por cada um dos clusters. Um servidor principal receberá as solicitações dos usuários e enviará de volta o endereço IP do servidor relevante para o qual o usuário possa trabalhar isso.

O cluster de banco de dados usará a replicação de banco de dados para obter consistência entre os bancos de dados.

Também deve haver um balanceador de carga geográfico - para atribuir o balanceador de carga regional a cada usuário para obter a melhor resposta.

Estou usando o .NET + MSSQL para o jogo.

Obrigado!

romano
fonte
2
Quando você diz "infraestrutura", você quer dizer software, hardware, serviços ou apenas deseja que critiquemos seu plano existente?
Tetrad
1
@ Nate - estamos planejando ampliar, não duplicar -, por isso deve ser totalmente escalável.
roman
2
-1 porque teddziuba.com/2008/04/im-going-to-scale-my-foot-up-y.html - Você não cobre nenhum requisito de capacidade, diz que o jogo não é fragmentado, mas está dividido , etc. A natureza das otimizações de desempenho - incluindo escalabilidade - requer informações específicas e não há melhor arquitetura absoluta.
1
Eu reformularia sua pergunta para algo mais concreto. O que é 'melhor', de maneira factual e não subjetiva? Você quer dizer mais fácil de escalar, mais fácil de gerenciar, mais fácil de começar, mais rápido ou o quê?
A Comunista Duck
1
"Mais fácil" também é subjetivo. Mais fácil para quem, em que período de tempo, considerando quais recursos? As trocas de pilha funcionam melhor com perguntas específicas - "Eu construí este servidor usando LINQ e MSSQL, mas caiu após 70 transações / segundo. Aqui estão as minhas duas principais transações representando 73% do meu tempo de execução, como devo aumentar minha taxa de transferência? "

Respostas:

6

Não há melhor arquitetura sem conhecer muito mais seus requisitos, por exemplo. o tipo de interações entre os personagens, quantos dados serão persistentes e assim por diante.

Se você consegue lidar com 1 segundo de latência, provavelmente pode hospedar 1000 jogadores em um único servidor sem problemas - mas isso realmente entra em conflito com a idéia de um FPS, pois eles normalmente exigem latência muito menor, por exemplo. menos de 100ms. Mas um sistema que pode lidar com alta latência pode se dar ao luxo de fazer tudo via passagem de mensagens, o que torna a consistência bastante trivial. Fornecer sua lógica é bastante simples, isto é - a lógica complexa fica ainda pior quando você a transforma em um sistema baseado em mensagens, em vez de um sistema de objetos bloqueados - mas tudo depende das necessidades de seu aplicativo.

Da mesma forma, se você não persiste em muitos dados, não precisa da máquina de banco de dados, mas sem saber disso, é difícil dizer. Se você persiste em pequenas quantidades de dados, e talvez apenas faça isso no final de um torneio ou algo assim, novamente você não precisa de um banco de dados separado, certamente não de um cluster deles. Por outro lado, se você não persiste muito, mas lê muito, é aí que os bancos de dados replicados podem ajudá-lo - mas também indica que um banco de dados relacional pode não ser a melhor correspondência para o seu problema. Geralmente, um cache na memória é uma solução melhor. Da mesma forma, se não houver interações no estilo de transação entre caracteres, a consistência se tornará menos importante. (E se houver apenas algumas dessas transações, você poderá torná-las um caso especial.)

De fato, tenha cuidado ao adotar um RDBMS apenas porque é o que está sendo feito em grandes sistemas. Embora eu pessoalmente aprove o uso deles em jogos on-line, é melhor analisar seus requisitos e descobrir sua estratégia de persistência a partir disso, em vez de usar seu banco de dados preferido e tentar ajustá-lo com caches e replicação para ajustá-lo ao seu aplicativo. Você pode achar que tudo o que precisa é a capacidade de gerar relatórios offline; nesse caso, provavelmente é melhor ter um processo em segundo plano registrando do mecanismo de persistência do jogo em um RDBMS remoto em outro lugar.

Kylotan
fonte
4

Isenção de responsabilidade: minha experiência em programação de jogos é baseada em jogos single-player do lado do cliente, mas eu tenho experiência em aplicativos da Web (especificamente na pilha da Microsoft), de modo que é de onde eu venho com esta resposta, acho que muito aplicar, mas sem testar de fato um servidor de jogo real, é difícil dizer como ele será aplicado, mas aqui vai. Saiba disso: não implantei um servidor de jogos, apenas aplicativos da web.

Eu sugeriria uma abordagem de duas camadas (servidor). Uma camada de banco de dados e uma "aplicação"; com a terceira camada (apresentação) sendo seu cliente do jogo.

Os bancos de dados relacionais são ótimos na consulta de dados e decentes na gravação de dados. A chave é serializar as gravações do banco de dados em pedaços de tamanho gerenciáveis ​​que o cluster pode manipular. As edições mais avançadas (data center / empresa) do SQL Server oferecem suporte a cluster e replicação. Eu começaria construindo um pequeno cluster e executando algumas consultas nele para ver como ele funciona.

Na camada do aplicativo, se você estiver executando o "zoneamento" ou algo semelhante, provavelmente poderá fugir sem configurar nenhum cluster e simplesmente configurar um servidor por zona. Se suas zonas ficarem muito grandes, você poderá configurar um cluster para cada zona.

Você deseja criar um processo de serialização para enviar dados da camada de aplicativo -> camada de banco de dados. A chave é ter vários níveis de serialização em andamento. Algo assim :

  • Nível 1: salve no banco de dados a cada X segundos, inclui dados críticos:
    • Saúde do jogador
    • Itens / Captadores de Jogador
  • Nível 2: salve no banco de dados a cada 2X segundos, inclui dados médios:
    • Localizações dos jogadores
    • Localizações NPC
  • Nível 3: Tudo o mais, com a menor frequência possível

Isso manterá suas gravações consistentes e previsíveis. Dependendo da natureza do seu jogo, você poderá ter gravações pouco frequentes no banco de dados. A chave é perceber que, se o seu servidor de aplicativos travasse, você teria que voltar a ficar on-line a partir do estado em seu banco de dados; portanto, serializar o inventário de jogadores a cada 90 minutos pode deixá-los chateados.

Para ler dados, você deseja carregar o máximo possível de memória na camada de aplicativos e garantir que todo o seu código use esse conjunto de memórias; em segundo plano, você pode sincronizar o conjunto de memórias com o banco de dados. Como Joe aponta, haverá momentos em que você precisará de transações "em tempo real". Ao serializar a maioria de suas gravações, você ainda deve ter E / S suficiente em seu banco de dados para realizar transações em tempo real quando necessário, presumindo hardware suficiente no servidor / cluster de banco de dados.

Nate
fonte
-1 porque você acabou de jogar fora o ACID e está apenas usando o banco de dados como um grande armazenamento de dados. Tudo bem, o agendador de disco do Windows é ruim o suficiente para ainda melhorar o desempenho, e você provavelmente pode fazer algumas métricas offline limpas com os dados, mas ainda precisa do ACID - ou seja, um banco de dados - apoiando as transações no próprio jogo, em tempo real (ish).
Embora escasso, era para isso que eu estava indo no último parágrafo. Estou recomendando um pouco de híbrido, onde você usa a IN-Memory sempre que possível e o banco de dados quando necessário.
Nate
O problema é que você encobriu o que está na memória, que é um outro banco de dados inteiro, e não deu nenhuma orientação sobre como implementá-lo, que é a parte mais complicada.
É verdade que a pergunta era sobre arquitetura de imagem geral, não detalhes de implementação.
Nate
É verdade, mas você deixou de fora toda a camada intermediária. É um RDB de baixa latência? Um ODB? Armazenamento de chave / valor? Sem banco de dados e desistir de ACID? STM ou travamento? Para ser justo, é muito difícil responder a isso, porque não há muita informação na pergunta, mas toda essa resposta faz com o diagrama da arquitetura é colocar a grande bolha no meio com um "?" nele e conectar mais dois serviços a ele, na verdade não preencher o que "?" é.