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

Garantindo a confiabilidade de plataformas em grande escala

Operar qualquer plataforma distribuída escalável exige um compromisso com a confiabilidade, para garantir que os clientes tenham o que precisam quando precisam. As dependências podem ser bastante complexas, especialmente em uma plataforma tão grande quanto a Roblox. Construir serviços confiáveis significa que, independentemente da complexidade e do status das dependências, qualquer serviço não será interrompido (ou seja, terá alta disponibilidade), funcionará sem bugs (ou seja, terá alta qualidade) e sem erros (ou seja, terá tolerância a falhas).

Por que a confiabilidade é importante

Nossa equipe de Identidade de Conta está comprometida em alcançar maior confiabilidade, já que os serviços de conformidade que criamos são componentes essenciais da plataforma. A quebra da conformidade pode ter consequências graves. O custo de bloquear a operação natural do Roblox é muito alto, com recursos adicionais necessários para a recuperação após uma falha e uma experiência do usuário prejudicada.

A abordagem típica à confiabilidade concentra-se principalmente na disponibilidade, mas, em alguns casos, os termos são confundidos e usados incorretamente. A maioria das métricas de disponibilidade apenas avalia se os serviços estão ativos e funcionando, enquanto aspectos como tolerância à partição e consistência são, por vezes, esquecidos ou mal compreendidos. 

De acordo com o teorema CAP, qualquer sistema distribuído só pode garantir dois desses três aspectos; portanto, nossos serviços de conformidade sacrificam um pouco da consistência para serem altamente disponíveis e tolerantes a partições. No entanto, nossos serviços sacrificaram pouco e encontraram mecanismos para alcançar boa consistência com mudanças arquitetônicas razoáveis, explicadas abaixo.

O processo para alcançar maior confiabilidade é iterativo, com medições rigorosas acompanhando o trabalho contínuo para prevenir, identificar, detectar e corrigir defeitos antes que incidentes ocorram. Nossa equipe identificou grande valor nas seguintes práticas:

  • Medição correta — Construir observabilidade total em torno de como a qualidade é entregue aos clientes e como as dependências nos proporcionam qualidade.
  • Antecipação proativa — Realizar atividades como revisões arquitetônicas e avaliações de risco de dependências.
  • Priorizar a correção — Dar maior atenção à resolução de relatórios de incidentes para o serviço e as dependências ligadas ao nosso serviço.

Construir maior confiabilidade exige uma cultura de qualidade. Nossa equipe já estava investindo em desenvolvimento orientado para o desempenho e sabe que o sucesso de um processo depende de sua adoção. A equipe adotou esse processo na íntegra e aplicou as práticas como padrão. O diagrama a seguir destaca os componentes do processo:

O poder da medição correta

Antes de nos aprofundarmos nas métricas, há um breve esclarecimento a ser feito sobre as medições de Nível de Serviço.

  • O SLO (Objetivo de Nível de Serviço) é a meta de confiabilidade que nossa equipe busca atingir (por exemplo, 99,999%).
  • O SLI (Indicador de Nível de Serviço) é a confiabilidade alcançada em um determinado período (por exemplo, 99,975% em fevereiro passado).
  • SLA (Acordo de Nível de Serviço) é a confiabilidade acordada para ser entregue e esperada por nossos consumidores em um determinado período (por exemplo, 99,99% por semana).

O SLI deve refletir a disponibilidade (sem respostas não processadas ou ausentes), a tolerância a falhas (sem erros de serviço) e a qualidade alcançada (sem erros inesperados). Portanto, definimos nosso SLI como a “Taxa de Sucesso” das respostas bem-sucedidas em comparação com o total de solicitações enviadas a um serviço. Respostas bem-sucedidas são aquelas solicitações que foram despachadas no tempo e na forma adequados, o que significa que não ocorreram erros de conectividade, de serviço ou erros inesperados.

Este SLI ou Índice de Sucesso é coletado do ponto de vista dos consumidores (ou seja, clientes). A intenção é medir a experiência real de ponta a ponta entregue aos nossos consumidores, para que tenhamos certeza de que os SLAs estão sendo cumpridos. Não fazer isso criaria uma falsa sensação de confiabilidade que ignora todas as preocupações de infraestrutura para nos conectarmos com nossos clientes. Da mesma forma que o SLI do consumidor, coletamos o SLI de dependência para rastrear qualquer risco potencial. Na prática, todos os SLAs de dependência devem estar alinhados com o SLA do serviço, e há uma dependência direta entre eles. A falha de um implica a falha de todos. Também rastreamos e relatamos métricas do próprio serviço (ou seja, do servidor), mas essa não é a fonte prática para alta confiabilidade.

Além dos SLIs, cada compilação coleta métricas de qualidade que são relatadas pelo nosso fluxo de trabalho de CI. Essa prática ajuda a reforçar fortemente os controles de qualidade (ou seja, cobertura de código) e a relatar outras métricas significativas, como conformidade com padrões de codificação e análise estática de código. Esse tópico foi abordado anteriormente em outro artigo, Construindo Microsserviços Orientados pelo Desempenho. A observância diligente da qualidade faz a diferença quando se trata de confiabilidade, pois quanto mais investimos em alcançar excelentes pontuações, mais confiantes ficamos de que o sistema não falhará em condições adversas.

Nossa equipe possui dois painéis. Um oferece total visibilidade tanto do SLI de Consumidores quanto do SLI de Dependências. O segundo mostra todas as métricas de qualidade. Estamos trabalhando para mesclar tudo em um único painel, de modo que todos os aspectos que nos interessam fiquem consolidados e prontos para serem relatados em qualquer intervalo de tempo.

Antecipar Falhas

Realizar revisões arquitetônicas é parte fundamental da confiabilidade. Primeiro, determinamos se há redundância e se o serviço tem meios para sobreviver quando as dependências caem. Além das ideias típicas de replicação, a maioria dos nossos serviços aplicou técnicas aprimoradas de hidratação de cache duplo, estratégias de recuperação dupla (como filas locais de failover) ou estratégias contra perda de dados (como suporte transacional). Esses tópicos são extensos o suficiente para merecerem outra postagem no blog, mas, em última análise, a melhor recomendação é implementar ideias que considerem cenários de desastre e minimizem qualquer penalidade de desempenho.

Outro aspecto importante a se antecipar é qualquer coisa que possa melhorar a conectividade. Isso significa ser proativo em relação à baixa latência para os clientes e prepará-los para tráfego muito intenso usando técnicas de controle de cache, sidecars e políticas de alto desempenho para tempos limite, disjuntores de circuito e tentativas de recuperação. Essas práticas se aplicam a qualquer cliente, incluindo caches, lojas, filas e clientes interdependentes em HTTP e gRPC. Isso também significa melhorar os sinais de integridade dos serviços e compreender que as verificações de integridade desempenham um papel importante em toda a orquestração de contêineres. A maioria dos nossos serviços emite sinais de degradação como parte do feedback da verificação de integridade e verifica se todos os componentes críticos estão funcionais antes de enviar sinais de integridade.

Dividir os serviços em partes críticas e não críticas provou ser útil para focar na funcionalidade que mais importa. Costumávamos ter endpoints exclusivos para administradores no mesmo serviço e, embora não fossem usados com frequência, eles afetavam as métricas gerais de latência. Transferi-los para um serviço próprio teve um impacto positivo em todas as métricas.

A Avaliação de Risco de Dependência é uma ferramenta importante para identificar problemas potenciais com dependências. Isso significa que identificamos dependências com baixo SLI e solicitamos o alinhamento do SLA. Essas dependências precisam de atenção especial durante as etapas de integração, por isso dedicamos tempo extra para comparar e testar se as novas dependências estão maduras o suficiente para nossos planos. Um bom exemplo é a adoção antecipada que fizemos do Roblox Storage-as-a-Service. A integração com esse serviço exigiu o registro de tickets de bug e reuniões periódicas de sincronização para comunicar descobertas e feedback. Todo esse trabalho usa a tag “confiabilidade” para que possamos identificar rapidamente sua origem e prioridades. A caracterização ocorreu com frequência até que tivéssemos a confiança de que a nova dependência estava pronta para nós. Esse trabalho extra ajudou a elevar a dependência ao nível de confiabilidade exigido que esperamos entregar, atuando juntos por um objetivo comum.

Trazer estrutura ao caos

Nunca é desejável ter incidentes. Mas, quando eles acontecem, há informações significativas a serem coletadas e aprendidas para nos tornarmos mais confiáveis. Nossa equipe possui um relatório de incidentes que vai além do relatório típico de toda a empresa, de modo que nos concentramos em todos os incidentes, independentemente da escala de seu impacto. Identificamos a causa raiz e priorizamos todo o trabalho para mitigá-la no futuro. Como parte desse relatório, convocamos outras equipes para corrigir incidentes de dependência com alta prioridade, acompanhamos a resolução adequada, fazemos uma retrospectiva e procuramos padrões que possam se aplicar a nós.

A equipe produz um Relatório Mensal de Confiabilidade por Serviço que inclui todos os SLIs explicados aqui, quaisquer tickets que tenhamos aberto por motivos de confiabilidade e quaisquer possíveis incidentes associados ao serviço. Estamos tão acostumados a gerar esses relatórios que o próximo passo natural é automatizar sua extração. Realizar essa atividade periódica é importante e serve como um lembrete de que a confiabilidade está sendo constantemente monitorada e considerada em nosso desenvolvimento.

Nossa instrumentação inclui métricas personalizadas e alertas aprimorados para que sejamos notificados o mais rápido possível quando problemas conhecidos e esperados ocorrerem. Todos os alertas, incluindo falsos positivos, são revisados semanalmente. Nesse ponto, é importante aperfeiçoar toda a documentação para que nossos usuários saibam o que esperar quando os alertas forem acionados e quando ocorrerem erros, e assim todos saibam o que fazer (por exemplo, manuais de procedimentos e diretrizes de integração são alinhados e atualizados com frequência).

Em última análise, a adoção da qualidade em nossa cultura é o fator mais crítico e decisivo para alcançar maior confiabilidade. Podemos observar como essas práticas, aplicadas ao nosso trabalho diário, já estão dando frutos. Nossa equipe é obcecada por confiabilidade, e essa é nossa conquista mais importante. Aumentamos nossa consciência sobre o impacto que possíveis defeitos poderiam ter e quando eles poderiam ser introduzidos. Os serviços que implementaram essas práticas têm atingido consistentemente seus SLOs e SLAs. Os relatórios de confiabilidade que nos ajudam a acompanhar todo o trabalho que temos feito são uma prova do trabalho realizado por nossa equipe e constituem lições inestimáveis para informar e influenciar outras equipes. É assim que a cultura de confiabilidade abrange todos os componentes de nossa plataforma.

O caminho para uma maior confiabilidade não é fácil, mas é necessário se você deseja construir uma plataforma confiável que reimagine como as pessoas se conectam.

Alberto é engenheiro de software sênior na equipe de Identidade de Conta da Roblox. Ele está na indústria de jogos há muito tempo, com créditos em muitos títulos de jogos AAA e plataformas de mídia social, com forte foco em arquiteturas altamente escaláveis. Agora, ele está ajudando a Roblox a alcançar crescimento e maturidade por meio da aplicação das melhores práticas de desenvolvimento.