Arquitetura real · Júnior
Stack Overflow: um monólito em poucos servidores
Arquitetura real em produção. Pontos centrais: Escalabilidade Horizontal vs Vertical, Microsserviços vs Monólito e Fundamentos de Cache.
Resposta curta
Arquitetura real em produção. Pontos centrais: Escalabilidade Horizontal vs Vertical, Microsserviços vs Monólito e Fundamentos de Cache. O Stack Overflow é o site de perguntas e respostas para programadores. Virou exemplo clássico de que um sistema muito usado não precisa ser dividido em dezenas de serviços.
01 · CONTEXTO
O caso do site que ficou em poucos servidores
O Stack Overflow é o site de perguntas e respostas para programadores. Virou exemplo clássico de que um sistema muito usado não precisa ser dividido em dezenas de serviços. Em 2009 a High Scalability resumiu o ponto: o caso é um argumento forte de que escalar para cima ainda é viável para uma classe potencialmente grande de problemas. Aqui vemos dois retratos: o de 2009, da High Scalability, e o de fevereiro de 2016, de Nick Craver, engenheiro do Stack Overflow. Os números são sempre da época.
Em 2009 o site tinha 16 milhões de páginas vistas por mês e rodava em pouquíssimas máquinas: dois servidores web e um servidor de banco com 48 GB de RAM. A arquitetura tinha duas camadas, com o código web acessando o banco diretamente.
O navegador pede a página a um dos servidores web, que executa o código da aplicação.
O código web consulta o banco diretamente, sem camada de serviço no meio.
A fonte registra que, na maior parte das vezes, o gargalo era o banco, que concentra o trabalho.
02 · A ARQUITETURA DE 2016
Muito tráfego, poucas máquinas
Num dia de fevereiro de 2016 o balanceador do Stack Overflow recebeu cerca de 209 milhões de requisições HTTP, das quais cerca de 66 milhões eram carregamentos de página. Para isso o post lista 4 servidores SQL Server, 11 servidores web, 2 de Redis, 3 do mecanismo de tags, 3 de Elasticsearch e 4 balanceadores HAProxy.
O autor afirma que, depois das otimizações e do hardware novo, bastaria um único servidor web, e que isso já foi testado sem querer, com sucesso, algumas vezes. Ele mesmo ressalva que funcionar não quer dizer que seja uma boa ideia: a sobra de máquinas existe de propósito.
O DNS fica num provedor externo com servidores próximos de quase todo mundo. O tráfego chega ao balanceador, que termina o TLS e escolhe o destino pelo cabeçalho de host.
O balanceador reparte as requisições entre os servidores web. A aplicação de perguntas e respostas é multi-tenant: um único programa atende todos os sites da rede.
Antes de ir ao banco, a camada web consulta o cache: primeiro o da própria aplicação e depois o Redis.
Se nenhum cache tem o dado, a consulta vai ao SQL Server, a fonte da verdade da qual vêm também os dados do Redis e do Elasticsearch.
O principal leva quase toda a carga e copia os dados de forma assíncrona para réplicas, inclusive em outro datacenter de recuperação.
As buscas saem do SQL e vão ao Elasticsearch; a camada de serviço roda o mecanismo de tags e mantém o índice de busca atualizado.
O mecanismo de tags é consultado, por exemplo, quando alguém abre a página de perguntas de uma tag. Ele roda na camada de serviço, separada da camada web, e não dentro dela.
03 · CACHE EM DOIS NÍVEIS
Redis como segundo nível, e a invalidação
O Stack Overflow usa um cache de dois níveis. O primeiro, chamado L1 no post, é o cache HTTP dentro da própria aplicação nos servidores web; o segundo, L2, é o Redis. Quando um servidor erra nos dois, busca o valor na origem, por exemplo uma consulta ao banco, e grava o resultado no cache local e no Redis. O próximo servidor pode errar o L1, mas acha o valor no L2 e poupa a consulta.
Cache local em vários servidores cria um problema de consistência: se um servidor remove um valor, os outros continuam com cópias. O post resolve isso com o mecanismo de publicar e assinar do próprio Redis, que avisa os demais servidores para limpar o L1. Apesar de cerca de 160 bilhões de operações por mês, cada instância de Redis fica abaixo de 2% de CPU.
O servidor A recebe um pedido e não acha o valor nem no cache local nem no Redis.
Ele busca o valor no banco e grava o resultado no cache local e no Redis.
O servidor B erra o cache local, mas acha o valor no Redis e não consulta o banco.
Quando A remove o valor, publica um aviso no Redis e B limpa a cópia local, mantendo as camadas coerentes.
04 · MONÓLITO E ESCALA
Banco para cima, aplicação para fora, monólito onde ajuda
A aplicação principal de perguntas e respostas é um monólito multi-tenant: um único programa serve todos os sites da rede, e o post diz que daria para rodar a rede inteira num único pool de aplicação num único servidor. Mesmo assim há outras aplicações separadas, como Careers e as APIs.
Existe também uma camada de serviço, separada da web, para o trabalho pesado, como o mecanismo de tags. O motivo dado é que carregar de tempos em tempos os posts alterados é caro, e não se quer repetir esse carregamento em todos os nove servidores web: três vezes bastam e dão segurança.
Em 2009 a mesma fonte organizou as lições em torno de escalar para cima e para fora: bancos escalam para cima e aplicações escalam para fora, e por isso é útil separar as funções de aplicação e de banco para que cada uma cresça de forma independente. A tabela resume os prós e contras que a fonte aponta.
| Critério | Escalar para cima | Escalar para fora |
|---|---|---|
| Onde a fonte aplica | Banco de dados | Camada de aplicação |
| Condição ou ponto fraco | Falta de redundância; poucas aplicações escalam linearmente com os processadores | Custo de licenças quando o software não é de código aberto |
| O que a aplicação precisa | Memória barata e abundante para o banco | Guardar o estado no banco para somar servidores |
A falta de redundância do scale up, apontada em 2009, aparece respondida em 2016: o post afirma que todos os servidores e serviços têm redundância dupla em outro datacenter, e explica que a sobra de servidores web serve a builds graduais, folga e redundância. Veja disponibilidade e balanceamento de carga para esses padrões.
A divisão, portanto, não é dogma: o monólito é mantido onde ajuda e a carga cara é separada onde o custo pede.
05 · ONDE O BANCO DOEU
Gargalo, joins e o que tirar do SQL
Em 2009 a fonte registra que o banco era o gargalo na maior parte das vezes. Ela também diz que o Stack Overflow copiou parte do desenho de banco da Wikipedia, o que foi um erro: exigiria uma refatoração grande para evitar joins excessivos, que ainda custavam caro mesmo com o banco quase todo na RAM. A mesma fonte lembra que memória é barata e que encher o servidor de RAM dá desempenho quase de graça. É um exemplo de antipadrão de desempenho.
Em 2016 o uso de SQL é simples de propósito: o post diz que simples é rápido, e o banco tem só uma stored procedure. O que é caro sai do SQL: a busca vai para o Elasticsearch, porque a CPU de SQL é cara e a de Elastic é barata, e o desenho de busca fica independente do banco transacional.
Para atualizações em tempo real, como notificações e votos, o site usa websockets em vez de polling, que é muito mais eficiente na escala deles, com cerca de 500 mil conexões simultâneas no pico.
O ganho de tempo de resposta veio de hardware novo e de muito ajuste nas próprias aplicações: uma página de pergunta levou em média cerca de 22,7 ms, dos quais cerca de 19,1 ms na aplicação. O autor reforça que desempenho continua sendo uma funcionalidade.
06 · LIMITES E LIÇÕES
O que levar e o que não copiar
Em entrevista, antes de propor microsserviços, pergunte qual problema real a divisão resolveria. O caso mostra um desenho com monólito, cache em camadas, banco forte com réplicas e busca separada, e o ponto é justificar cada peça por um gargalo, não por moda.
Perguntas frequentes
O que é Stack Overflow: um monólito em poucos servidores?
Arquitetura real em produção. Pontos centrais: Escalabilidade Horizontal vs Vertical, Microsserviços vs Monólito e Fundamentos de Cache.
O que o design de Stack Overflow: um monólito em poucos servidores cobre?
Ele está organizado nestas seções: O caso do site que ficou em poucos servidores, Muito tráfego, poucas máquinas, Redis como segundo nível, e a invalidação, Banco para cima, aplicação para fora, monólito onde ajuda, Gargalo, joins e o que tirar do SQL e O que levar e o que não copiar.
Quanto tempo leva Stack Overflow: um monólito em poucos servidores e qual é o nível?
Leva cerca de 12 minutos para ler e tem nível Júnior.
Agora projete você mesmo
Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.