Na New Relic, definir e estabelecer indicadores de nível de serviço (SLIs) e objetivos de nível de serviço (SLOs) é um aspecto cada vez mais importante de nossa prática de engenharia de confiabilidade de site (SRE). Não é novidade que SLIs e SLOs são uma parte importante da alta- práticas de confiabilidade funcionais, mas planejar como aplicá-las no contexto de uma arquitetura de software moderna e complexa do mundo real pode ser um desafio, especialmente descobrir o que medir e como medi-lo.

Nesta postagem do blog, usaremos uma versão altamente simplificada da arquitetura New Relic para mostrar alguns exemplos concretos e práticos de como nossa equipe de confiabilidade define e mede SLIs e SLOs para nossa própria plataforma de software moderna.

Como definimos SLI e SLO

É fácil se perder na névoa de siglas, então, antes de nos aprofundarmos, aqui está uma definição rápida e fácil de como os indicadores de nível de serviço (SLIs) e os objetivos de nível de serviço (SLOs) estão relacionados aos acordos de nível de serviço (SLAs):

SLI SLO SLA
X deve ser verdade... Y parte do tempo, ou então.

Quando aplicamos esta definição à disponibilidade, aqui estão alguns exemplos: 

  • SLIs são as principais medidas para determinar a disponibilidade de um sistema.
  • SLOs são metas que definimos para quanta disponibilidade esperamos de um sistema.
  • SLAs são contratos legais que explicam o que acontece se o sistema não cumprir seu SLO.

Os SLIs existem para ajudar as equipes de engenharia a tomar melhores decisões. O desempenho do seu SLO é uma informação crítica para se ter ao tomar decisões sobre quão intensamente e rapidamente você pode impulsionar seus sistemas. Os SLOs também são pontos de dados importantes para outros engenheiros quando eles fazem suposições sobre suas dependências do seu serviço ou sistema. Por último, sua organização maior deve usar seus SLIs e SLOs para tomar decisões informadas sobre os níveis de investimento e sobre o equilíbrio entre o trabalho de confiabilidade e a velocidade de engenharia.

Defina SLIs e SLOs em relação aos limites do sistema

Quando olhamos para o interior de uma plataforma de software moderna, o nível de complexidade pode ser assustador, para dizer o mínimo. As plataformas geralmente compreendem centenas, senão milhares, de componentes exclusivos, incluindo bancos de dados, nós de serviço, balanceadores de carga, filas de mensagens e assim por diante. Estabelecer SLIs e SLOs voltados para o cliente, como disponibilidade geral ou tempo de atividade para cada componente, pode não ser viável.

É por isso que recomendamos focar em SLIs e SLOs nos limites do sistema, em vez de em componentes individuais. As plataformas tendem a ter muito menos limites de sistema do que componentes individuais, e os dados SLI/SLO obtidos dos limites do sistema também são mais valiosos. Esses dados são úteis para os engenheiros que mantêm o sistema, para os clientes do sistema e para os tomadores de decisão de negócios.

Um limite de sistema é um ponto em que um ou mais componentes expõem funcionalidade a clientes externos. Por exemplo, na plataforma New Relic, temos um serviço de login que representa a funcionalidade para um usuário autenticar um conjunto de credenciais usando uma API.

É provável que o serviço de login tenha vários componentes internos – nós de serviço, um banco de dados e uma réplica de banco de dados somente leitura. Mas esses componentes internos não representam limites do sistema porque não os expomos ao cliente. Em vez disso, esse grupo de componentes atua em conjunto para expor os recursos do serviço de login.

Usando essa ideia de limites do sistema, podemos pensar em nosso exemplo simplificado do New Relic como um conjunto de unidades lógicas (ou níveis) – um sistema de interface, um nível de serviço (que inclui o serviço de login), dois sistemas de dados separados e um sistema de ingestão – e não como um emaranhado de componentes individuais. E, claro, temos mais uma fronteira de sistema, que é a fronteira entre todos esses serviços como um todo e nossos clientes.

Diagrama de limites do sistema mostrando a camada de UI/API, serviço de login, camada de armazenamento/qualidade de dados, camada de dados legados e ingestão/roteamento de dados.

Focar nos SLIs de limite do sistema nos permite capturar o valor dessas medições críticas do sistema, simplificando significativamente as medições que precisamos implementar.

Estabeleça uma linha de base para limites de serviço com um clique

Decidir por onde começar a definir seus limites de serviço e o que significa “confiabilidade” para sua equipe, sistema e clientes é uma tarefa difícil. O gerenciamento de nível de serviço no New Relic oferece uma solução fácil, porque você pode encontrar sua linha de base de confiabilidade e então personalizar SLIs e SLOs a partir daí.

Por exemplo, a New Relic identifica os SLIs mais comuns para um determinado serviço, na maioria das vezes alguma medida de disponibilidade e latência, e verifica os dados históricos de um serviço para determinar a melhor configuração inicial. Em toda a plataforma, você encontrará maneiras de configurar SLIs automaticamente, como mostraremos aqui, ou você pode criá-los manualmente com consultas NRQL.

Se você estiver procurando uma configuração com um clique para estabelecer uma linha de base para SLIs e SLOs no New Relic, basta seguir estas etapas:

  1. Faça login no New Relic e selecione APM no menu de navegação na parte superior.
  2. Selecione a entidade de serviço onde você deseja estabelecer SLIs.
  3. Em seguida, no menu à esquerda, role para baixo até Relatórios e selecione a opção Níveis de Serviço.
  4. Você deverá ver uma tela semelhante a esta:
A captura de tela do relatório de níveis de serviço mostra um botão Adicionar objetivos de nível de serviço de linha de base

A partir daqui, você pode simplesmente selecionar o botão Adicionar objetivos de nível de serviço baseline e deixar que o New Relic defina seus SLIs e SLOs. Não se esqueça de verificar a documentação de gerenciamento de nível de serviço para ver como os níveis de serviço do New Relic funcionam e encontrar mais maneiras de personalizar seus SLIs e SLOs.

SLI + SLO, uma receita simples

Você pode aplicar os conceitos de SLI, SLO e limites do sistema aos diferentes componentes que compõem sua plataforma moderna. E embora as especificidades de como aplicar esses conceitos variem de acordo com o tipo de componente, na New Relic usamos o mesma receita geral em cada caso:

  1. Identifique os limites do sistema em nossa plataforma.
  2. Identifique os recursos voltados para o cliente que existem em cada limite do sistema.
  3. Articule uma definição em linguagem simples do que significa a disponibilidade de cada serviço ou função.
  4. Defina um ou mais SLIs para essa definição.
  5. Comece a medir para obter uma linha de base.
  6. Defina um SLO para cada métrica e acompanhe nosso desempenho em relação a ela.
  7. Itere e refine nosso sistema e ajuste os SLOs ao longo do tempo.

Cada limite do sistema possui um conjunto exclusivo de funcionalidades e dependências a serem consideradas. Vamos dar uma olhada mais de perto em como essas considerações moldam a forma como definimos nossos SLIs e SLOs para cada camada.

A funcionalidade dos serviços impulsiona os SLIs

Parte da definição de disponibilidade da nossa plataforma significa que ela pode ingerir dados dos nossos clientes e encaminhá-los para o local certo para que outros sistemas possam consumi-los. Estamos lidando aqui com dois processos distintos — ingestão e roteamento — portanto, precisamos de um SLO e um SLI para cada um.

O diagrama da camada de ingestão de dados mostra os dados ingeridos e os dados roteados

É fundamental começarmos com definições em linguagem simples do que significa “disponibilidade” para cada um desses serviços para nossos clientes que usam o sistema. No caso da funcionalidade de ingestão, os clientes em questão são os usuários finais do nosso sistema— as pessoas que nos enviam seus dados. Nesse caso, a definição de disponibilidade pode ser: “Se eu enviar meus dados para a New Relic no formato correto, eles serão aceitos e processados”.

Então, podemos usar essa definição em linguagem simples para determinar qual métrica corresponde melhor à forma como ela define a disponibilidade. A melhor métrica aqui é provavelmente o número de solicitações HTTP POST contendo dados recebidos que são aceitas com respostas de status OK 200. Expressando isso em termos de um SLO, poderíamos dizer que “99,9% das cargas bem formadas obtêm 200 respostas de status OK”.

Uma definição em linguagem simples para a funcionalidade de roteamento de dados poderia ser assim: “As mensagens recebidas estão disponíveis para outros sistemas consumirem nosso barramento de mensagens sem demora." Com essa definição, podemos definir o SLI e o SLO como: "99,xx% das mensagens recebidas estão disponíveis para outros sistemas consumirem do nosso barramento de mensagens dentro de 500 milissegundos." Para medir esse SLO - 99,95% - podemos comparar o carimbo de data/hora de ingestão em cada mensagem com o carimbo de data/hora de quando a mensagem ficou disponível no barramento de mensagens.

OK, ótimo! Agora temos um SLO para cada serviço. Na prática, porém, nos preocupamos menos com o SLO do que com o SLI, porque os números do SLO são fáceis de ajustar. Podemos querer ajustar um número de SLO por vários motivos comerciais. Por exemplo, podemos começar com um SLO mais baixo para um sistema menos maduro e aumentar o SLO ao longo do tempo à medida que o sistema amadurece. É por isso que dizemos que é importante que a funcionalidade desejada de um serviço impulsione o SLI.

SLIs são proxies amplos de disponibilidade

Os dados ingeridos pela nossa plataforma são armazenados em uma de nossas principais camadas de dados. Para a New Relic, este é o NRDB, nosso cluster de banco de dados proprietário. Em termos de linguagem simples, o NRDB está funcionando corretamente se pudermos inserir dados rapidamente no sistema, e os clientes podem consultar seus dados novamente.

Nos bastidores, o NRDB é um sistema massivo e distribuído com milhares de nós e diferentes tipos de trabalhadores e nós o monitoramos para rastrear métricas como uso de memória, tempo de coleta de lixo, durabilidade e disponibilidade de dados e eventos verificados por segundo. Mas no nível do limite do sistema, podemos apenas observar a latência de inserção e os tempos de resposta da consulta como proxies para essas classes de erros subjacentes.

Quando definimos um SLI para tempos de resposta de consulta, não vamos olhar para as médias, porque as médias mentem. Mas também não queremos olhar para o percentil 99,9, porque essas provavelmente serão as consultas estranhas do pior cenário. Em vez disso, concentramo-nos no percentil 95 ou 99, porque isso nos dá uma visão da experiência da grande maioria dos nossos clientes, sem nos concentrarmos demasiado nos valores atípicos.

Neste ponto, podemos configurar uma condição de alerta para ser acionada se perdermos o SLI do tempo de resposta da consulta. Isso nos permite rastrear com que frequência violamos esse alerta, o que, por sua vez, nos informa com que frequência satisfazemos nosso SLI – quanto tempo estamos disponíveis? Definitivamente, não queremos usar esse alerta para acordar as pessoas no meio da noite – esse limite deveria ser maior – mas é uma maneira fácil de monitorar nosso desempenho na contabilidade do SLO.

Articulamos esses SLIs e SLOs para que nossos clientes saibam o que esperar ao consultar seus dados. Na verdade, podemos combinar vários SLOs em uma medida de confiabilidade amigável ao cliente:

Exemplo de dois SLOs combinados em uma medida de confiabilidade

Começamos com estes dois SLOs:

  • 99.95% das consultas bem formuladas receberão respostas bem formuladas.
  • 99.9% das dúvidas serão respondidas em menos de 1000ms.

Nós os combinamos nesta medida de confiabilidade: 99,9% das consultas bem formadas receberão respostas bem formadas em menos de 1000 ms.

Avalie a experiência do cliente para entender SLO/SLIs para UIs

Atribuímos um serviço à nossa camada de UI – esperamos que seja rápido e sem erros. Mas, para medir o desempenho da UI, temos que mudar nossa perspectiva. Até agora, nossas preocupações com confiabilidade eram centradas no servidor, mas, com o nível de interface, queremos medir a experiência dos clientes e como ela é afetada pelo frontend. Temos que definir vários SLIs para a UI.

Indicadores de nível de serviço para diagrama de IU mostram um recurso e vários SLIs

Para o tempo de carregamento da página, por exemplo, usamos o tempo de carregamento do percentil 95 ou 99 em vez da média. Além disso, definimos SLIs diferentes para regiões geográficas diferentes. Mas para aplicativos da Web modernos, o tempo de carregamento da página é apenas um SLI a ser considerado.

Também queremos criar SLIs para medir a capacidade de resposta de diferentes interações no navegador, como acionamento de ações AJAX e alterações no modelo de objeto de documento (DOM).

E, claro, precisamos definir SLIs para taxas de erro de JavaScript e possivelmente priorizar os refinamentos da experiência do usuário em determinados navegadores mais do que em outros.

Dependências rígidas exigem SLOs mais altos: a camada de rede

Até agora, explicamos como definimos SLIs e SLOs para diferentes serviços em nossa plataforma, mas agora abordaremos uma parte crítica de nossa infraestrutura principal, a rede. Esses são nossos SLIs e SLOs mais importantes porque estabelecem a base de toda a nossa plataforma. O nível de rede é uma dependência difícil para todos os nossos serviços.

O exemplo da camada de rede inclui vários recursos, vários SLIs e um SLO por recurso

Para nossa rede, definimos três recursos: precisamos de conectividade entre zonas de disponibilidade (AZs), conectividade entre racks dentro de uma AZ e endpoints com balanceamento de carga que expõem serviços tanto interna quanto externamente. Precisamos de um SLO mais alto para esses recursos.

Com essas camadas de dependências surgem possíveis cenários de falha:

  • Se algo der errado na camada da UI, será uma falha isolada da qual deve ser fácil recuperar.
  • Se nosso serviço falhar, a UI será afetada, mas podemos implementar algum cache de UI para reduzir esse impacto.
  • Se a infraestrutura de dados cair, o nível de serviço e a interface de usuário também ficarão inativos, e a interface de usuário não poderá se recuperar até que o nível de dados e o nível de serviço voltem a ficar online.
  • Se a rede cair, tudo cairá e precisaremos de um tempo de recuperação antes que o sistema fique online novamente. Como os sistemas não retornam no instante em que uma dependência se recupera, nosso tempo médio de recuperação (MTTR) aumenta.
Cenários de falha de vários níveis

Em geral, presumimos que perderemos uma pequena ordem de magnitude no tempo de atividade em cada nível. Se esperarmos um SLO de 99,9% de disponibilidade para serviços executados na camada de rede, definimos um SLO de 99,99% de disponibilidade para a própria rede.

É difícil implementar cenários de degradação harmoniosos contra interrupções graves da infraestrutura, por isso investimos na confiabilidade dessas camadas de infraestrutura e definimos SLOs mais elevados. Esta prática é uma das coisas mais importantes que podemos fazer para a saúde geral da nossa plataforma.

Uma última verificação geral

Depois de definir SLIs e SLOs para os serviços que fornecem nossa plataforma geral, temos uma ótima maneira de entender onde estão nossos pontos críticos de confiabilidade. E nossas equipes de engenharia têm uma ótima maneira de entender, priorizar e defender suas decisões de confiabilidade.

Ainda precisamos implementar uma última verificação de SLI e SLO: precisamos medir a experiência do cliente de ponta a ponta.

Para fazer isso, executamos um script de monitoramento sintético no New Relic que representa um fluxo de trabalho simples e completo do cliente. Ele envia alguns dados para nossa plataforma e, em seguida, faz login e consulta esses dados específicos. Se detectarmos qualquer discrepância significativa entre o desempenho deste script e as expectativas definidas em nossos SLOs, sabemos que precisamos revisitar nossa metodologia SLI.

Seis coisas para lembrar

Para encerrar, encorajamos você a se lembrar destes seis pontos quando se trata de definir SLIs e SLOs:

  1. Defina SLIs e SLOs para recursos específicos nos limites do sistema.
  2. Cada instância lógica de um sistema (por exemplo, um fragmento de banco de dados) obtém seu próprio SLO.
  3. Combine SLIs para um determinado serviço em um único SLO
  4. Documente e compartilhe seus contratos SLI/SLO.
  5. Suponha que tanto os seus SLOs quanto os SLIs evoluirão com o tempo.
  6. Mantenha-se envolvido: os SLOs representam um compromisso contínuo.

Demora um pouco para construir uma boa prática de confiabilidade, mas não importa quanto tempo e esforço você investe, acreditamos firmemente que não é possível construir arquiteturas de software resilientes e confiáveis sem definições claras das demandas e da disponibilidade que você está estabelecendo para seus sistemas. Em relação aos SLOs e SLIs, relembrar o surgimento de AIOps para compreender o crescimento da tecnologia também pode ser útil.

Uma versão anterior desta postagem do blog foi publicada em outubro de 2018, adotada de uma palestra proferida no FutureStack18 intitulada “SLOs e SLIs no mundo real: um mergulho profundo”. Matthew Flaming, ex-vice-presidente de confiabilidade de sites da New Relic, contribuiu para esta postagem.