O conteúdo deste site foi traduzido usando inteligência artificial (IA) ou tecnologia de tradução automática e pode conter erros.

Skip to content

Roblox volta ao ar

A partir de 28 de outubro e com resolução total em 31 de outubro, o Roblox sofreu uma interrupção de 73 horas.¹ Cinquenta milhões de jogadores usam o Roblox regularmente todos os dias e, para criar a experiência que nossos jogadores esperam, nossa estrutura envolve centenas de serviços online internos. Como em qualquer serviço de grande escala, temos interrupções de serviço de tempos em tempos, mas a duração prolongada dessa interrupção torna o caso particularmente digno de nota. Pedimos sinceras desculpas à nossa comunidade pelo tempo de inatividade.

Estamos compartilhando esses detalhes técnicos para que nossa comunidade compreenda a causa raiz do problema, como o resolvemos e o que estamos fazendo para evitar que questões semelhantes ocorram no futuro. Gostaríamos de reiterar que não houve perda de dados de usuários nem acesso de terceiros não autorizados a qualquer informação durante o incidente.

As equipes de engenharia da Roblox e de suporte técnico da HashiCorp uniram esforços para restabelecer o serviço da Roblox. Gostaríamos de agradecer à equipe da HashiCorp, que disponibilizou recursos incríveis e trabalhou incansavelmente conosco até que os problemas fossem resolvidos.

Resumo da interrupção

A interrupção foi única tanto em duração quanto em complexidade. A equipe teve que enfrentar uma série de desafios em sequência para entender a causa raiz e restabelecer o serviço.

  • A interrupção durou 73 horas.
  • A causa raiz foi devido a dois problemas. A ativação de um recurso de streaming relativamente novo no Consul sob uma carga de leitura e gravação excepcionalmente alta levou a um conflito excessivo e baixo desempenho. Além disso, nossas condições específicas de carga desencadearam um problema de desempenho patológico no BoltDB. O sistema de código aberto BoltDB é usado dentro do Consul para gerenciar logs de gravação antecipada para eleição de líder e replicação de dados. 
  • Um único cluster do Consul suportando múltiplas cargas de trabalho exacerbou o impacto desses problemas.
  • Os desafios no diagnóstico desses dois problemas, em grande parte não relacionados e profundamente ocultos na implementação do Consul, foram os principais responsáveis pelo tempo de inatividade prolongado. 
  • Os sistemas de monitoramento críticos que teriam proporcionado melhor visibilidade sobre a causa da interrupção dependiam de sistemas afetados, como o Consul. Essa combinação dificultou severamente o processo de triagem.
  • Fomos criteriosos e cuidadosos em nossa abordagem para restaurar o Roblox de um estado de indisponibilidade total prolongada, o que também levou um tempo considerável.
  • Aceleramos os esforços de engenharia para melhorar nosso monitoramento, remover dependências circulares em nossa pilha de observabilidade, bem como acelerar nosso processo de inicialização. 
  • Estamos trabalhando para migrar para várias zonas de disponibilidade e data centers.
  • Estamos corrigindo os problemas no Consul que foram a causa raiz deste evento.

Prefácio: Nosso ambiente de cluster e HashiStack

A infraestrutura central do Roblox é executada nos data centers do Roblox. Implantamos e gerenciamos nosso próprio hardware, bem como nossos próprios sistemas de computação, armazenamento e rede sobre esse hardware. A escala de nossa implantação é significativa, com mais de 18.000 servidores e 170.000 contêineres.

Para operar milhares de servidores em vários locais, utilizamos um conjunto de tecnologias comumente conhecido como “HashiStack”. Nomad, Consul e Vault são as tecnologias que usamos para gerenciar servidores e serviços em todo o mundo, e que nos permitem orquestrar contêineres que suportam os serviços da Roblox.

O Nomad é usado para agendar tarefas. Ele decide quais contêineres serão executados em quais nós e em quais portas estarão acessíveis. Ele também valida a integridade dos contêineres. Todos esses dados são retransmitidos para um Registro de Serviços, que é um banco de dados de combinações de IP:Porta. Os serviços da Roblox usam o Registro de Serviços para se localizarem mutuamente, de modo que possam se comunicar. Esse processo é chamado de “descoberta de serviços”. Usamos o Consul para descoberta de serviços, verificações de integridade, bloqueio de sessão (para sistemas de alta disponibilidade construídos sobre ele) e como um armazenamento KV.

O Consul é implantado como um cluster de máquinas em duas funções. Os “votantes” (5 máquinas) mantêm com autoridade o estado do cluster; os “não votantes” (5 máquinas adicionais) são réplicas somente leitura que auxiliam no dimensionamento das solicitações de leitura. A qualquer momento, um dos votantes é eleito pelo cluster como líder. O líder é responsável por replicar dados para os outros votantes e determinar se os dados gravados foram totalmente confirmados.  O Consul usa um algoritmo chamado Raft para a eleição do líder e para distribuir o estado pelo cluster de forma a garantir que cada nó no cluster concorde com as atualizações. Não é incomum que o líder mude por meio da eleição várias vezes ao longo de um determinado dia.

A seguir, uma captura de tela recente do painel do Consul na Roblox após o incidente. Muitas das principais métricas operacionais mencionadas nesta postagem do blog aparecem em níveis normais. O tempo de aplicação de KV, por exemplo, é considerado normal quando inferior a 300 ms e, neste momento, é de 30,6 ms. O líder do Consul teve contato com outros servidores do cluster nos últimos 32 ms, o que é muito recente.

1. Operações normais do Consul no Roblox

Nos meses que antecederam o incidente de outubro, a Roblox atualizou do Consul 1.9 para o Consul 1.10 para aproveitar um novo recurso de streaming. Esse recurso de streaming foi projetado para reduzir significativamente a CPU e a largura de banda de rede necessárias para distribuir atualizações em clusters de grande escala, como o da Roblox.

Detecção inicial (28/10 13:37)

Na tarde de 28 de outubro, o desempenho do Vault foi prejudicado e um único servidor Consul apresentava alta carga de CPU. Os engenheiros da Roblox começaram a investigar. Nesse momento, os jogadores não foram afetados.

Triagem inicial (28/10 13:37 – 29/10 02:00)

A investigação inicial sugeriu que o cluster do Consul, do qual o Vault e muitos outros serviços dependem, não estava funcionando corretamente.  Especificamente, as métricas do cluster do Consul mostravam latência de gravação elevada para o armazenamento KV subjacente no qual o Consul armazena dados. A latência no 50º percentil nessas operações era normalmente inferior a 300 ms, mas agora era de 2 segundos. Problemas de hardware não são incomuns na escala da Roblox, e o Consul pode sobreviver a falhas de hardware. No entanto, se o hardware estiver apenas lento, em vez de apresentar falha, isso pode afetar o desempenho geral do Consul. Nesse caso, a equipe suspeitou que o desempenho degradado do hardware fosse a causa raiz e iniciou o processo de substituição de um dos nós do cluster do Consul. Essa foi nossa primeira tentativa de diagnosticar o incidente. Por volta dessa hora, a equipe da HashiCorp se juntou aos engenheiros da Roblox para ajudar no diagnóstico e na correção. Todas as referências a “a equipe” e “a equipe de engenharia” a partir deste ponto se referem tanto à equipe da Roblox quanto à da HashiCorp.

Mesmo com o novo hardware, o desempenho do cluster do Consul continuou prejudicado. Às 16h35, o número de jogadores online caiu para 50% do normal.

2. CCU durante o Player Drop às 16h35 PST

Essa queda coincidiu com uma degradação significativa na integridade do sistema, o que acabou resultando em uma interrupção total do sistema. Por quê? Quando um serviço do Roblox deseja se comunicar com outro serviço, ele depende do Consul para ter informações atualizadas sobre a localização do serviço com o qual deseja se comunicar. No entanto, se o Consul não estiver em bom estado, os servidores têm dificuldade para se conectar. Além disso, o Nomad e o Vault dependem do Consul; portanto, quando o Consul não está em bom estado, o sistema não consegue agendar novos contêineres nem recuperar segredos de produção usados para autenticação. Em resumo, o sistema falhou porque o Consul era um ponto único de falha e não estava em bom estado.

Nesse momento, a equipe desenvolveu uma nova teoria sobre o que estava dando errado: aumento do tráfego. Talvez o Consul estivesse lento porque nosso sistema atingiu um ponto de ruptura, e os servidores nos quais o Consul estava rodando não conseguiam mais lidar com a carga? Essa foi nossa segunda tentativa de diagnosticar a causa raiz do incidente.

Dada a gravidade do incidente, a equipe decidiu substituir todos os nós do cluster do Consul por máquinas novas e mais potentes. Essas novas máquinas tinham 128 núcleos (um aumento de 2x) e discos SSD NVME mais novos e mais rápidos. Às 19h, a equipe migrou a maior parte do cluster para as novas máquinas, mas o cluster ainda não estava em bom estado. O cluster estava relatando que a maioria dos nós não conseguia acompanhar as gravações, e a latência no 50º percentil nas gravações KV ainda estava em torno de 2 segundos, em vez dos 300 ms ou menos habituais.

Tentativa de retorno ao serviço nº 1 (29/10, 02h00 – 04h00)

As duas primeiras tentativas de restaurar o cluster do Consul a um estado saudável não tiveram sucesso. Ainda observávamos uma latência elevada nas gravações KV, bem como um novo sintoma inexplicável que não conseguíamos compreender: o líder do Consul ficava regularmente fora de sincronia com os outros votantes. 

A equipe decidiu desligar todo o cluster do Consul e redefinir seu estado usando um snapshot de algumas horas antes – o início da interrupção. Entendemos que isso poderia causar uma pequena perda de dados de configuração do sistema (não perda de dados do usuário). Dada a gravidade da interrupção e nossa confiança de que poderíamos restaurar esses dados de configuração do sistema manualmente, se necessário, achamos que isso era aceitável. 

Esperávamos que a restauração a partir de um snapshot tirado quando o sistema estava saudável levasse o cluster a um estado saudável, mas tínhamos uma preocupação adicional. Embora o Roblox não tivesse nenhum tráfego gerado por usuários fluindo pelo sistema nesse momento, os serviços internos do Roblox ainda estavam ativos e acessando o Consul para saber a localização de suas dependências e atualizar suas informações de integridade. Essas leituras e gravações estavam gerando uma carga significativa no cluster. Estávamos preocupados que essa carga pudesse levar o cluster de volta a um estado não saudável imediatamente, mesmo que a reinicialização do cluster fosse bem-sucedida. Para resolver essa preocupação, configuramos o iptables no cluster para bloquear o acesso. Isso nos permitiria reiniciar o cluster de forma controlada e nos ajudaria a entender se a carga que estávamos colocando no Consul, independentemente do tráfego de usuários, era parte do problema.

A reinicialização ocorreu sem problemas e, inicialmente, as métricas pareciam boas. Quando removemos o bloqueio do iptables, a carga de descoberta de serviços e verificação de integridade proveniente dos serviços internos retornou conforme o esperado. No entanto, o desempenho do Consul começou a se degradar novamente e, eventualmente, voltamos ao ponto de partida: o percentil 50 nas operações de gravação KV estava de volta a 2 segundos. Os serviços que dependiam do Consul estavam começando a se marcar como “com problemas” e, eventualmente, o sistema voltou ao estado problemático já familiar. Eram agora 04h00. Havia claramente algo em nossa carga no Consul que estava causando problemas e, após mais de 14 horas de incidente, ainda não sabíamos o que era.

Tentativa de Retorno ao Serviço #2 (29/10 04:00 – 30/10 02:00)

Tínhamos descartado falha de hardware. Hardware mais rápido não havia ajudado e, como descobrimos mais tarde, potencialmente prejudicava a estabilidade. Reiniciar o estado interno do Consul também não havia ajudado. Não havia tráfego de usuários entrando, mas o Consul continuava lento. Tínhamos usado o iptables para permitir que o tráfego voltasse ao cluster gradualmente. Será que o cluster estava simplesmente sendo empurrado de volta a um estado instável pelo volume de milhares de contêineres tentando se reconectar? Essa foi nossa terceira tentativa de diagnosticar a causa raiz do incidente.

A equipe de engenharia decidiu reduzir o uso do Consul e, em seguida, reintroduzi-lo de forma cuidadosa e sistemática. Para garantir que tivéssemos um ponto de partida limpo, também bloqueamos o tráfego externo restante. Montamos uma lista exaustiva de serviços que usam o Consul e implementamos alterações de configuração para desativar todo o uso não essencial. Esse processo levou várias horas devido à grande variedade de sistemas e tipos de alterações de configuração visados. Os serviços do Roblox que normalmente tinham centenas de instâncias em execução foram reduzidos para um dígito. A frequência da verificação de integridade foi diminuída de 60 segundos para 10 minutos para dar ao cluster um espaço adicional para respirar. Às 16h do dia 29 de outubro, mais de 24 horas após o início da interrupção, a equipe iniciou sua segunda tentativa de colocar o Roblox de volta online. Mais uma vez, a fase inicial dessa tentativa de reinicialização parecia promissora, mas às 2h do dia 30 de outubro, o Consul estava novamente em um estado não saudável, desta vez com uma carga significativamente menor dos serviços do Roblox que dependem dele.

Nesse momento, ficou claro que o uso geral do Consul não era o único fator que contribuía para a degradação de desempenho que havíamos notado pela primeira vez no dia 28. Com essa constatação, a equipe mudou de estratégia novamente. Em vez de analisar o Consul da perspectiva dos serviços do Roblox que dependem dele, a equipe começou a examinar o funcionamento interno do Consul em busca de pistas.

Investigação sobre a contenção (30/10 02:00 – 30/10 12:00)

Nas 10 horas seguintes, a equipe de engenharia se aprofundou nos logs de depuração e nas métricas no nível do sistema operacional. Esses dados mostraram que as gravações no banco de dados KV do Consul estavam sendo bloqueadas por longos períodos. Em outras palavras, “conflito de acesso”. A causa do conflito não ficou imediatamente clara, mas uma teoria era que a mudança de servidores de 64 para 128 núcleos de CPU no início da interrupção poderia ter agravado o problema. Após analisar os dados do htop e os dados de depuração de desempenho mostrados nas capturas de tela abaixo, a equipe concluiu que valia a pena voltar para servidores de 64 núcleos, semelhantes aos usados antes da interrupção. A equipe começou a preparar o hardware: o Consul foi instalado, as configurações do sistema operacional foram verificadas três vezes e as máquinas foram preparadas para o serviço da maneira mais detalhada possível. A equipe então fez a transição do cluster do Consul de volta para servidores com 64 núcleos de CPU, mas essa mudança não ajudou. Essa foi nossa quarta tentativa de diagnosticar a causa raiz do incidente.

3. Em seguida, exibimos isso com um relatório de desempenho, conforme mostrado acima. A maior parte do tempo foi gasta em bloqueios de spin do kernel por meio do caminho de código da assinatura de streaming.
4. HTOP mostrando o uso da CPU em 128 núcleos.

Causas principais identificadas (30/10 12h00 – 30/10 20h00)

Há vários meses, ativamos um novo recurso de streaming do Consul em um subconjunto de nossos serviços. Esse recurso, projetado para reduzir o uso da CPU e a largura de banda de rede do cluster do Consul, funcionou conforme o esperado; portanto, nos meses seguintes, ativamos o recurso de forma incremental em mais serviços de back-end. Em 27 de outubro às 14h, um dia antes da interrupção, ativamos esse recurso em um serviço de back-end responsável pelo roteamento de tráfego. Como parte dessa implementação, a fim de nos prepararmos para o aumento de tráfego que normalmente observamos no final do ano, também aumentamos em 50% o número de nós que suportam o roteamento de tráfego. O sistema havia funcionado bem com streaming nesse nível por um dia antes do início do incidente, portanto, inicialmente não ficou claro por que seu desempenho havia mudado. No entanto, por meio da análise de relatórios de desempenho e gráficos de flame dos servidores Consul, vimos evidências de que os caminhos de código de streaming eram responsáveis pela contenção que causava o alto uso da CPU. Desativamos o recurso de streaming para todos os sistemas Consul, incluindo os nós de roteamento de tráfego. A propagação da alteração de configuração foi concluída às 15h51, momento em que o percentil 50 para gravações no Consul KV caiu para 300 ms. Finalmente, tivemos um avanço.

Por que o streaming era um problema? A HashiCorp explicou que, embora o streaming fosse, em geral, mais eficiente, ele utilizava menos elementos de controle de concorrência (canais Go) em sua implementação do que o long polling. Sob carga muito alta — especificamente, tanto uma carga de leitura muito alta quanto uma carga de gravação muito alta —, o design do streaming agrava a quantidade de contenção em um único canal Go, o que causa bloqueio durante as gravações, tornando-o significativamente menos eficiente. Esse comportamento também explicava o efeito de servidores com maior número de núcleos: esses servidores eram arquiteturas de soquete duplo com um modelo de memória NUMA. A contenção adicional nos recursos compartilhados, portanto, piorava nessa arquitetura. Ao desativar o streaming, melhoramos drasticamente a integridade do cluster do Consul.

Apesar do avanço, ainda não estávamos totalmente fora de perigo. Vimos o Consul elegendo intermitentemente novos líderes de cluster, o que era normal, mas também observamos alguns líderes apresentando os mesmos problemas de latência que vimos antes de desativarmos o streaming, o que não era normal. Sem nenhuma pista óbvia apontando para a causa raiz do problema de lentidão dos líderes, e com evidências de que o cluster estava saudável desde que certos servidores não fossem eleitos como líderes, a equipe tomou a decisão pragmática de contornar o problema impedindo que os líderes problemáticos permanecessem eleitos. Isso permitiu que a equipe se concentrasse em restaurar os serviços da Roblox que dependem do Consul para um estado saudável.

Mas o que estava acontecendo com os líderes lentos? Não descobrimos isso durante o incidente, mas os engenheiros da HashiCorp determinaram a causa raiz nos dias seguintes à interrupção. O Consul usa uma popular biblioteca de persistência de código aberto chamada BoltDB para armazenar logs do Raft. Ela não é usada para armazenar o estado atual dentro do Consul, mas sim um log contínuo das operações que estão sendo aplicadas. Para evitar que o BoltDB cresça indefinidamente, o Consul realiza snapshots regularmente. A operação de snapshot grava o estado atual do Consul no disco e, em seguida, exclui as entradas de log mais antigas do BoltDB. 

No entanto, devido ao design do BoltDB, mesmo quando as entradas de log mais antigas são excluídas, o espaço que o BoltDB ocupa no disco nunca diminui. Em vez disso, todas as páginas (segmentos de 4 KB dentro do arquivo) que foram usadas para armazenar dados excluídos são marcadas como “livres” e reutilizadas para gravações subsequentes. O BoltDB rastreia essas páginas livres em uma estrutura chamada “freelist”. Normalmente, a latência de gravação não é significativamente afetada pelo tempo que leva para atualizar a freelist, mas a carga de trabalho da Roblox expôs um problema de desempenho patológico no BoltDB que tornou a manutenção da freelist extremamente onerosa. 

Restaurando o serviço de cache (30/10 20:00 – 31/10 05:00)

Já haviam se passado 54 horas desde o início da interrupção. Com o streaming desativado e um processo em vigor para impedir que líderes lentos permanecessem eleitos, o Consul estava agora consistentemente estável. A equipe estava pronta para se concentrar no retorno ao serviço.

A Roblox usa um padrão típico de microsserviços para seu backend. Na base da “pilha” de microsserviços estão bancos de dados e caches. Esses bancos de dados não foram afetados pela interrupção, mas o sistema de cache, que normalmente lida com 1 bilhão de solicitações por segundo em suas múltiplas camadas durante a operação regular do sistema, estava em estado insalubre. Como nossos caches armazenam dados transitórios que podem ser facilmente repovoados a partir dos bancos de dados subjacentes, a maneira mais fácil de trazer o sistema de cache de volta a um estado saudável era reimplantá-lo.

O processo de reimplantação do cache encontrou uma série de problemas: 

  1. Provavelmente devido à reinicialização do snapshot do cluster do Consul que havia sido realizada anteriormente, os dados de agendamento internos que o sistema de cache armazena no Consul KV estavam incorretos. 
  2. As implantações de caches pequenos estavam demorando mais do que o esperado, e as implantações de caches grandes não estavam sendo concluídas. Descobriu-se que havia um nó com problema que o agendador de tarefas via como completamente aberto, em vez de com problema. Isso fez com que o agendador de tarefas tentasse agendar agressivamente tarefas de cache nesse nó, o que falhou porque o nó estava com problema. 
  3. A ferramenta de implantação automatizada do sistema de cache foi criada para dar suporte a ajustes incrementais em implantações de grande escala que já estavam lidando com tráfego em escala, e não a tentativas iterativas de inicializar um grande cluster do zero. 

A equipe trabalhou durante a noite para identificar e resolver esses problemas, garantir que os sistemas de cache fossem implantados corretamente e verificar a exatidão. Às 05h00 do dia 31 de outubro, 61 horas após o início da interrupção, tínhamos um cluster Consul em bom estado e um sistema de cache em bom estado. Estávamos prontos para ativar o restante do Roblox.

O Retorno dos Jogadores (31/10 05:00 – 31/10 16:00)

A fase final de retorno ao serviço começou oficialmente às 05:00 do dia 31. Assim como o sistema de cache, uma parte significativa dos serviços em execução havia sido desativada durante a interrupção inicial ou as fases de solução de problemas. A equipe precisava reiniciar esses serviços nos níveis de capacidade corretos e verificar se estavam funcionando corretamente. Isso ocorreu sem problemas e, às 10:00, estávamos prontos para abrir o serviço aos jogadores.

Com caches frios e um sistema sobre o qual ainda tínhamos dúvidas, não queríamos uma enxurrada de tráfego que pudesse potencialmente colocar o sistema de volta em um estado instável. Para evitar uma enxurrada, usamos o direcionamento de DNS para gerenciar o número de jogadores que podiam acessar o Roblox. Isso nos permitiu deixar entrar uma determinada porcentagem de jogadores selecionados aleatoriamente, enquanto outros continuavam sendo redirecionados para nossa página estática de manutenção. Sempre que aumentávamos a porcentagem, verificávamos a carga do banco de dados, o desempenho do cache e a estabilidade geral do sistema. O trabalho continuou ao longo do dia, aumentando o acesso em incrementos de aproximadamente 10%. Ficamos felizes em ver alguns de nossos jogadores mais dedicados descobrirem nosso esquema de direcionamento de DNS e começarem a trocar essas informações no Twitter para que pudessem obter acesso “antecipado” à medida que restabelecíamos o serviço. Às 16h45 de domingo, 73 horas após o início da interrupção, 100% dos jogadores receberam acesso e o Roblox estava totalmente operacional.

Análises adicionais e mudanças decorrentes da interrupção

Embora os jogadores tenham sido autorizados a retornar ao Roblox em 31 de outubro, o Roblox e a HashiCorp continuaram a refinar sua compreensão da interrupção ao longo da semana seguinte. Problemas específicos de contenção no novo protocolo de streaming foram identificados e isolados. Embora a HashiCorp tivesse testado o streaming em escala semelhante à do uso do Roblox, eles não haviam observado esse comportamento específico antes, pois ele se manifestava a partir de uma combinação de um grande número de streams e uma alta taxa de rotatividade. A equipe de engenharia da HashiCorp está criando novos benchmarks de laboratório para reproduzir o problema específico de contenção e realizando testes de escala adicionais. A HashiCorp também está trabalhando para melhorar o design do sistema de streaming a fim de evitar contenção sob carga extrema e garantir um desempenho estável nessas condições. 

Uma análise mais aprofundada do problema do “líder lento” também revelou a causa principal das gravações de dados Raft de dois segundos e dos problemas de consistência do cluster. Os engenheiros examinaram gráficos de chama como o abaixo para entender melhor o funcionamento interno do BoltDB.

5. Análise das operações da lista livre do BoltDB.
Conforme mencionado anteriormente, o Consul utiliza uma biblioteca de persistência chamada BoltDB para armazenar dados de log do Raft. Devido a um padrão de uso específico criado durante o incidente, as operações de gravação de 16 kB estavam se tornando muito maiores. Você pode ver o problema ilustrado nessas capturas de tela:
6. Detailed BoldDB statistics used in analysis.

A saída do comando anterior nos revela várias informações:

  • Este armazenamento de logs de 4,2 GB está armazenando apenas 489 MB de dados reais (incluindo todos os internos do índice). 3,8 GB são espaço “vazio”.
  • A lista de páginas livres tem 7,8 MB, pois contém quase um milhão de IDs de páginas livres.

Isso significa que, para cada acréscimo ao log (cada gravação Raft após algum processamento em lote), uma nova lista de páginas livres de 7,8 MB também estava sendo gravada no disco, mesmo que os dados brutos reais que estavam sendo acrescentados fossem de 16 kB ou menos. 

A contrapressão nessas operações também criou buffers TCP cheios e contribuiu para tempos de gravação de 2 a 3 segundos em líderes com problemas. A imagem abaixo mostra a pesquisa sobre o TCP Zero Windows durante o incidente.

7. Pesquisa sobre janelas zero do TCP. Quando o buffer de um receptor TCP começa a ficar cheio, ele pode reduzir sua janela de recepção. Se ficar cheio, ele pode reduzir a janela a zero, o que indica ao remetente TCP que pare de enviar.Legenda

A HashiCorp e a Roblox desenvolveram e implementaram um processo utilizando as ferramentas existentes do BoltDB para “compactar” o banco de dados, o que resolveu os problemas de desempenho.

Melhorias recentes e próximos passos

Já se passaram 2,5 meses desde a interrupção. O que temos feito? Aproveitamos esse tempo para aprender o máximo possível com a interrupção, ajustar as prioridades de engenharia com base no que aprendemos e fortalecer agressivamente nossos sistemas. Um dos valores da Roblox é Respeitar a Comunidade e, embora pudéssemos ter publicado um post mais cedo para explicar o que aconteceu, sentimos que devíamos isso a vocês, nossa comunidade: fazer progressos significativos na melhoria da confiabilidade de nossos sistemas antes de publicar. 

A lista completa de melhorias de confiabilidade concluídas e em andamento é muito longa e detalhada para este artigo, mas aqui estão os principais itens:

Melhorias na telemetria

Havia uma dependência circular entre nossos sistemas de telemetria e o Consul, o que significava que, quando o Consul estava com problemas, não tínhamos os dados de telemetria que teriam facilitado a identificação do que estava errado. Removemos essa dependência circular. Nossos sistemas de telemetria não dependem mais dos sistemas que estão configurados para monitorar.

Ampliamos nossos sistemas de telemetria para oferecer melhor visibilidade do desempenho do Consul e do BoltDB. Agora recebemos alertas altamente direcionados se houver qualquer sinal de que o sistema está se aproximando do estado que causou essa interrupção. Também ampliamos nossos sistemas de telemetria para oferecer mais visibilidade dos padrões de tráfego entre os serviços da Roblox e o Consul. Essa visibilidade adicional do comportamento e do desempenho do nosso sistema em vários níveis já nos ajudou durante atualizações do sistema e sessões de depuração.

Expansão para várias zonas de disponibilidade e data centers

Executar todos os serviços de back-end da Roblox em um único cluster do Consul nos deixou expostos a uma interrupção dessa natureza. Já montamos os servidores e a rede para um data center adicional, geograficamente distinto, que hospedará nossos serviços de back-end. Estamos trabalhando para migrar para várias zonas de disponibilidade dentro desses data centers; fizemos grandes modificações em nosso roteiro de engenharia e em nossos planos de pessoal para acelerar esses esforços.

Atualizações do Consul e fragmentação

O Roblox continua crescendo rapidamente, portanto, mesmo com vários clusters do Consul, queremos reduzir a carga que colocamos sobre o Consul. Analisamos como nossos serviços utilizam o armazenamento KV e as verificações de integridade do Consul e dividimos alguns serviços críticos em seus próprios clusters dedicados, reduzindo a carga sobre nosso cluster central do Consul para um nível mais seguro.

Alguns serviços essenciais da Roblox estão usando o armazenamento KV do Consul diretamente como um local conveniente para armazenar dados, embora tenhamos outros sistemas de armazenamento que provavelmente sejam mais adequados. Estamos no processo de migrar esses dados para um sistema de armazenamento mais adequado. Quando concluída, essa migração também reduzirá a carga sobre o Consul.

Descobrimos uma grande quantidade de dados KV obsoletos. A exclusão desses dados obsoletos melhorou o desempenho do Consul.

Estamos trabalhando em estreita colaboração com a HashiCorp para implantar uma nova versão do Consul que substitua o BoltDB por um sucessor chamado bbolt, que não apresenta o mesmo problema de crescimento ilimitado da lista livre. Adiamos intencionalmente esse esforço para o ano novo a fim de evitar uma atualização complexa durante nosso pico de tráfego de fim de ano. A atualização está sendo testada agora e será concluída no primeiro trimestre.

Melhorias nos procedimentos de inicialização e gerenciamento de configuração

O esforço de retorno ao serviço foi retardado por vários fatores, incluindo a implantação e o aquecimento dos caches necessários aos serviços da Roblox. Estamos desenvolvendo novas ferramentas e processos para tornar esse processo mais automatizado e menos propenso a erros. Em particular, redesenhamos nossos mecanismos de implantação de cache para garantir que possamos ativar rapidamente nosso sistema de cache a partir de um estado inicial. A implementação disso está em andamento.

Trabalhamos com a HashiCorp para identificar várias melhorias no Nomad que facilitarão a ativação de tarefas de grande porte após um longo período de indisponibilidade. Essas melhorias serão implantadas como parte de nossa próxima atualização do Nomad, prevista para o final deste mês.

Desenvolvemos e implantamos mecanismos para alterações mais rápidas na configuração das máquinas.

Reintrodução do streaming

Inicialmente, implantamos o streaming para reduzir o uso da CPU e a largura de banda de rede do cluster Consul. Assim que uma nova implementação for testada em nossa escala com nossa carga de trabalho, esperamos reintroduzi-la cuidadosamente em nossos sistemas.

Uma observação sobre a nuvem pública

Após uma interrupção como essa, é natural perguntar se a Roblox consideraria migrar para a nuvem pública e permitir que um terceiro gerenciasse nossos serviços básicos de computação, armazenamento e rede.

Outro dos valores da Roblox é “Ter uma Visão de Longo Prazo”, e esse valor influencia fortemente nossa tomada de decisões. Construímos e gerenciamos nossa própria infraestrutura básica no local porque, em nossa escala atual e, mais importante, na escala que sabemos que alcançaremos à medida que nossa plataforma crescer, acreditamos que essa seja a melhor maneira de apoiar nossos negócios e nossa comunidade. Especificamente, ao construir e gerenciar nossos próprios data centers para serviços de back-end e de borda de rede, conseguimos controlar significativamente os custos em comparação com a nuvem pública. Essas economias influenciam diretamente o valor que podemos pagar aos criadores na plataforma. Além disso, possuir nosso próprio hardware e construir nossa própria infraestrutura de borda nos permite minimizar variações de desempenho e gerenciar cuidadosamente a latência de nossos jogadores em todo o mundo. Desempenho consistente e baixa latência são essenciais para a experiência de nossos jogadores, que não estão necessariamente localizados perto dos data centers dos provedores de nuvem pública.

Observe que não estamos ideologicamente presos a nenhuma abordagem específica: usamos a nuvem pública para casos de uso em que isso faz mais sentido para nossos jogadores e desenvolvedores. Por exemplo, usamos a nuvem pública para capacidade de pico, grande parte de nossos fluxos de trabalho de DevOps e a maior parte de nossas análises internas. Em geral, consideramos a nuvem pública uma boa ferramenta para aplicativos que não são críticos em termos de desempenho e latência e que são executados em escala limitada. No entanto, para nossas cargas de trabalho mais críticas em termos de desempenho e latência, optamos por construir e gerenciar nossa própria infraestrutura no local. Fizemos essa escolha sabendo que isso exige tempo, dinheiro e talento, mas também sabendo que nos permitirá construir uma plataforma melhor. Isso está alinhado com nosso valor “Ter uma visão de longo prazo”.

Estabilidade do sistema desde a interrupção

A Roblox normalmente recebe um pico de tráfego no final de dezembro. Temos muito mais trabalho a fazer em termos de confiabilidade, mas temos o prazer de informar que a Roblox não teve um único incidente significativo de produção durante o pico de dezembro, e que o desempenho e a estabilidade tanto do Consul quanto do Nomad durante esse pico foram excelentes. Parece que nossas melhorias imediatas em confiabilidade já estão valendo a pena e, à medida que nossos projetos de longo prazo forem concluídos, esperamos resultados ainda melhores.

Considerações finais

Gostaríamos de agradecer à nossa comunidade global do Roblox pela compreensão e apoio. Outro dos nossos valores no Roblox é “Assumir a Responsabilidade”, e assumimos total responsabilidade pelo que aconteceu aqui. Gostaríamos de, mais uma vez, expressar nossos sinceros agradecimentos à equipe da HashiCorp. Seus engenheiros entraram em ação para nos ajudar logo no início dessa interrupção sem precedentes e não nos abandonaram. Mesmo agora, dois meses após a interrupção, os engenheiros da Roblox e da HashiCorp continuam colaborando estreitamente para garantir que estejamos, coletivamente, fazendo tudo o que podemos para evitar que uma interrupção semelhante volte a ocorrer.

Por fim, queremos agradecer aos nossos colegas da Roblox por confirmarem por que este é um lugar incrível para se trabalhar. Na Roblox, acreditamos na civilidade e no respeito. É fácil ser civilizado e respeitoso quando as coisas estão indo bem, mas o verdadeiro teste é como tratamos uns aos outros quando as coisas ficam difíceis. Em algum momento durante uma interrupção de 73 horas, com o tempo passando e o estresse aumentando, não seria surpresa ver alguém perder a calma, dizer algo desrespeitoso ou questionar em voz alta de quem era a culpa por tudo isso. Mas não foi isso que aconteceu. Nós nos apoiamos mutuamente e trabalhamos juntos como uma equipe, sem parar, até que o serviço voltasse a funcionar normalmente. É claro que não estamos orgulhosos dessa interrupção e do impacto que ela teve em nossa comunidade, mas estamos orgulhosos de como nos unimos como equipe para trazer o Roblox de volta à vida e de como tratamos uns aos outros com civilidade e respeito em cada etapa do caminho.

Aprendemos muito com essa experiência e estamos mais comprometidos do que nunca em tornar o Roblox uma plataforma mais forte e confiável daqui para frente.

Mais uma vez, obrigado. 

¹ Observe que todas as datas e horários nesta postagem do blog estão no horário padrão do Pacífico (PST).