Arquitetura real · Pleno
WhatsApp: 2 milhões de conexões por servidor (Erlang/FreeBSD)
Arquitetura real em produção. Pontos centrais: WebSocket e presença.
Resposta curta
Arquitetura real em produção. Pontos centrais: WebSocket e presença. No início de 2012, o blog do WhatsApp mostrou um único servidor com mais de dois milhões de conexões TCP abertas, e com folga de CPU e memória. Dois anos depois, uma palestra resumida pelo High Scalability falava em 465 milhões de usuários mensais e picos de 147 milhões de telefones…
01 · CONTEXTO
Dois milhões de conexões em uma máquina
No início de 2012, o blog do WhatsApp mostrou um único servidor com mais de dois milhões de conexões TCP abertas, e com folga de CPU e memória. Dois anos depois, uma palestra resumida pelo High Scalability falava em 465 milhões de usuários mensais e picos de 147 milhões de telefones conectados ao mesmo tempo.
O mesmo resumo traz o volume de mensagens: 19 bilhões entrando e 40 bilhões saindo por dia. Este caso olha por baixo desse volume: como uma pilha com Erlang e FreeBSD sustenta conexões persistentes em escala e o que a equipe fez para que uma falha não se espalhasse.
Para o aluno, o interesse está em dois temas já vistos na trilha: protocolos de comunicação baseados em conexão aberta, e o escalonamento horizontal e vertical de servidores que guardam estado de conexão.
02 · O CAMINHO DA MENSAGEM
Um telefone, uma conexão, poucos componentes
Segundo o resumo, telefones conectam a servidores de chat e de multimídia, e o chat conversa com um armazenamento transitório e com bancos de conta, perfil, push e grupo.
O telefone se conecta a um servidor de chat; é por essa conexão aberta que ele entrega a mensagem.
Enquanto a mensagem está em trânsito entre os usuários, o backend a retém num armazenamento transitório.
O servidor de chat também consulta bancos de conta, perfil, push e grupo.
O servidor entrega ao destinatário o texto, as notificações e as mensagens de presença, como digitando ou conectado.
A multimídia segue por servidores próprios, e o banco só guarda informação sobre a mídia enquanto ela é entregue.
Há três famílias de mensagens para o telefone: o texto em si, notificações como mudança de assunto de grupo, e mensagens de presença. Como mensagens e mídia só são guardadas enquanto são entregues, a arquitetura gira em torno de vazão, cache e partição, e não de armazenamento durável.
03 · CONEXÕES POR SERVIDOR
Por que o número caiu de dois milhões para um milhão
A máquina de 2012 rodava FreeBSD 8.2-STABLE com Erlang R14B03. Mesmo com mais de dois milhões de sockets abertos, a medição mostrava cerca de 42% de CPU ociosa, o que indica margem de sobra.
| Aspecto | Blog de 2012 | Palestra de 2014 |
|---|---|---|
| Conexões por servidor | Mais de dois milhões | Cerca de um milhão |
| Versão de Erlang | R14B03 | R16B01, com patches próprios |
| Folga por servidor | Sobrava CPU e memória | Mantida de propósito para absorver picos |
O resumo de 2014 explica a queda: com mais usuários, a equipe preferiu manter mais folga por servidor para os picos; os usuários também ficaram mais ativos; e funções que antes rodavam fora desses servidores passaram a rodar neles.
A frota resultante tinha cerca de 150 servidores de chat, com cerca de 1 milhão de telefones cada, e cerca de 250 de multimídia. A estratégia continuou sendo caixas grandes e poucos nós, porque, segundo o resumo, a complexidade operacional cresce com o número de nós e não com o de núcleos.
04 · ISOLAR GARGALOS
Desacoplar para que um problema não vire cascata
O princípio repetido na palestra é que o acoplamento forte causa falhas em cascata. Por isso tudo é particionado: se uma partição entra em apuros, as outras não são afetadas.
O vilão específico é o bloqueio de cabeça de fila: o item no início da fila trava todos os que vêm depois. A resposta foi separar filas por finalidade e por destino.
| Técnica | Problema que evita | Como o resumo descreve |
|---|---|---|
| Filas de leitura e escrita separadas | Latência de escrita travando os leitores | Escrita lenta não represa quem só lê |
| Filas separadas por nó de destino | Um nó ou rede com problema represando o trabalho para nós saudáveis | Só as mensagens para o nó com problema ficam represadas |
| Cast no lugar de call | Esperar resposta que ninguém usa, perdendo assincronia | Chamadas com resposta só ao voltar do banco; o resto é assíncrono |
05 · PARTICIONAR E REPLICAR
Partições em pares e um único dono por registro
Os serviços são divididos de 2 a 32 vias, a maioria em 32, e os nós rodam em pares, um primário e um secundário. O acesso a um registro é decidido por hash e termina num único processo Erlang.
Cada registro tem uma partição dona, escolhida por hash, e todo acesso a ele passa por um único processo.
Como cada fragmento é escrito por um só nó, a replicação do primário para o secundário segue em uma única direção.
Se o primário da partição A cai, o secundário passa a atender o tráfego primário e o secundário.
A partição B não percebe o problema da A: o desenho particionado limita o estrago a um pedaço.
O banco de multimídia em memória é um exemplo do tamanho disso: cerca de 2 TB de RAM em 16 partições guardavam cerca de 18 bilhões de registros. Quando um processo despachante virou gargalo, a equipe criou o gen_industry, uma camada acima do gen_factory, com vários despachantes em paralelo.
06 · LIÇÕES E LIMITES
O que levar para a entrevista
O resumo registra que o Mnesia, o banco do Erlang, pareceu uma grande fonte de problemas na escala deles, e que as maiores provas de estresse eram eventos mundiais, em especial futebol, com picos verticais de carga. O resumo celebra cerca de 40 milhões de usuários por engenheiro.
Um ponto operacional curto: Erlang permite atualizar código em produção sem parar o sistema, o que combina com servidores que seguram milhões de conexões vivas.
Na entrevista, o caso de chat em tempo real cobre o desenho geral. Este aqui entra como argumento de profundidade: conexões persistentes custam pouco por unidade, o que limita a escala é a folga para picos, e a defesa contra cascata é particionar, desacoplar e replicar em pares.
Perguntas frequentes
O que é WhatsApp: 2 milhões de conexões por servidor (Erlang/FreeBSD)?
Arquitetura real em produção. Pontos centrais: WebSocket e presença.
O que o design de WhatsApp: 2 milhões de conexões por servidor (Erlang/FreeBSD) cobre?
Ele está organizado nestas seções: Dois milhões de conexões em uma máquina, Um telefone, uma conexão, poucos componentes, Por que o número caiu de dois milhões para um milhão, Desacoplar para que um problema não vire cascata, Partições em pares e um único dono por registro e O que levar para a entrevista.
Quanto tempo leva WhatsApp: 2 milhões de conexões por servidor (Erlang/FreeBSD) e qual é o nível?
Leva cerca de 15 minutos para ler e tem nível Pleno.
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.