2023: a glória está a apenas 11 MB/s de distância
(thmsmlr.com)- Mesmo um site entre os 1000 maiores, com cerca de 200 milhões de visitas por mês, precisa de apenas 30 TB/mês olhando só para HTML, o que equivale a uma média de 11 MB/s de tráfego e pode ser suportado por um único servidor
- O cálculo parte do Business Insider, assumindo 2 páginas por visitante, 400 milhões de documentos HTML por mês, HTML comprimido de cerca de 75 KB, e que JS, CSS e imagens ficam a cargo de um CDN
- Executar na edge tem a vantagem de usar servidores próximos do usuário, mas se houver ida e volta ao banco de dados durante a renderização, a latência volta a ser puxada para onde está o banco de dados de origem
- A diferença de custo também é grande: a Hetzner oferece servidor com 16 núcleos, 64 GB de RAM e NVMe por US$ 0,34/hora, com 20 TB de tráfego grátis e depois US$ 1,5/TB, enquanto AWS e Vercel têm preços de banda muito mais altos
- A menos que seja uma tarefa que realmente exija nuvem, uma configuração com servidor único + SQLite + Litestream + CDN é mais simples e barata, evitando expansão horizontal desnecessária
O tamanho real de um site grande visto por 11 MB/s
- O Business Insider é usado como exemplo de site entre os 1000 maiores
- Segundo o SimilarWeb, ocupava a posição 587 no mundo e tinha cerca de 200 milhões de visitantes por mês
- Considerando uma média de 2 páginas por visitante, seria preciso servir 400 milhões de documentos HTML por mês
- Com base em um artigo de exemplo, o documento HTML padrão tem cerca de 75 KB após compressão
- Multiplicando isso, só o HTML exige cerca de 30 TB/mês de banda
- Convertendo 30 TB/mês para média, isso dá cerca de 11 MB/s
- No caso do Business Insider, isso corresponde a cerca de 150 requests/sec
- A premissa é que o HTML não use CDN, enquanto JS, CSS e imagens podem ser servidos por CDN
- Os 75 KB de HTML comprimido são relativamente grandes, então dependendo da implementação dá para reduzir o tamanho do HTML ou ajustar aumentando o número de requisições
- Em hardware moderno, gerar 11 MB/s de HTML com código de aplicação é uma exigência baixa
- Processadores de servidor AMD recentes oferecem 64 núcleos e 128 threads
- Há rumores de que os processadores Zen 5 Turin para servidores terão 192 núcleos, e em servidores dual-socket fala-se em configurações próximas de 400 núcleos e até 768 threads
- Por essa ótica, Docker, serverless e expansão horizontal nem sempre são escolhas necessárias
Execução na edge nem sempre reduz a latência
- O limite físico inferior de latência de ida e volta até o lado oposto da Terra é de cerca de 200 ms, considerando a velocidade da luz
- Na prática, muitas vezes leva algo em torno de 300 ms para chegar a um bom datacenter do outro lado do planeta
- Se JS, CSS e mídia forem entregues por CDN, reduzir em 300 ms o tempo de processamento no servidor na renderização inicial já produz um efeito parecido com mover o servidor para perto do usuário
- As tecnologias serverless de segunda geração reduziram bastante o problema antigo de cold boot, que podia facilmente consumir esse orçamento de 300 ms, mas a ida e volta ao banco de dados continua existindo
- Se a renderização da página exigir ao menos uma consulta ao banco, o servidor de edge precisará fazer ida e volta novamente até um local como us-east-1, onde está o banco de dados de origem
- A latência deixa de estar entre usuário e servidor de origem e passa a estar entre servidor de edge e servidor de origem
- Páginas complexas muitas vezes exigem 5 ou mais consultas ao banco de dados para renderizar
- Muitos frameworks web executam as consultas em sequência em um único thread, então várias idas e voltas entre datacenters podem ser mais lentas do que ir uma única vez ao servidor de origem
- Existe a regra prática de que a comunicação entre datacenters é 10 vezes mais lenta do que a comunicação dentro de um datacenter, e esta é 10 vezes mais lenta do que a comunicação dentro do mesmo dispositivo
- Nesse contexto, o SQLite local aparece como uma opção vantajosa para reduzir latência
Diferença de custo entre Hetzner, AWS e Vercel
- O servidor de 16 núcleos da Hetzner custa US$ 0,34/hora, incluindo 64 GB de RAM e drive NVMe
- Em comparação, um servidor x86 parecido na AWS, o EC2 m5a.4xlarge, custa US$ 0,68/hora
- A diferença de preço de banda é ainda maior
- A Hetzner inclui 20 TB de tráfego grátis e cobra US$ 1,5/TB depois disso
- A AWS inclui 100 GB grátis e cobra US$ 90/TB depois disso
- A Vercel é citada com o exemplo de US$ 200/TB após o primeiro 1 TB gratuito
- As franquias gratuitas dos provedores de nuvem facilitam a entrada no começo, mas podem se transformar em custos altos quando a escala cresce
Operando de forma simples com um servidor único
- A menos que exista um caso específico de uso de nuvem, como transcodificação de vídeo, execução de modelos próprios de IA ou outras tarefas que realmente imponham grande carga ao sistema, um site ou SaaS pode rodar em um único servidor
- Colocando o servidor na Virgínia, é possível oferecer latência abaixo de 100 ms para usuários de língua inglesa
- A configuração recomendada é manter tudo simples em torno de uma única máquina
- O banco de dados usa SQLite na mesma máquina
- O Litestream faz backup contínuo do SQLite
- CSS, JS e imagens são cacheados em CDN
- A renderização no servidor acontece perto do SQLite para reduzir ida e volta e melhorar o desempenho
- A implantação também não precisa ser complicada
- O CI pode enviar o código ao servidor via SCP
- O NGINX oferece suporte a deploy sem downtime
- Docker e virtualização são tratados como fatores que tornam a execução do código e o CI/CD mais lentos
Quando expansão horizontal é necessária — e quando não é
- Na maioria dos casos, a conversa sobre necessidade de expansão horizontal é exagerada
- A premissa é que o desempenho dos servidores está melhorando mais rápido do que o crescimento da internet
- Se a latência realmente for crucial, é possível adicionar servidores na Alemanha e na Califórnia
- As escritas são roteadas para o primary
- As leituras usam uma read replica local
- Essa configuração é escalável o suficiente, tem baixa complexidade operacional e custo bem menor
- Servir HTML na escala de 11 MB/s não precisa ser transformado em algo desnecessariamente difícil
1 comentários
Opiniões no Hacker News
Meu antigo pequeno negócio de hospedagem passou por seu auge e declínio exatamente nesse ponto, e na época eu não entendia o que estava acontecendo.
Quando crescemos no início dos anos 2000, a maior parte da receita vinha de stacks complexas, muitas vezes com configurações que os clientes queriam, como load balancers e firewalls redundantes, embora fossem mais do que eles realmente precisavam.
O failover frequentemente custava mais em complexidade operacional do que o benefício que trazia quando um servidor morria do jeito previsto. Também criamos uma plataforma de hospedagem em nuvem baseada em API para competir com a AWS, mas a receita atingiu o pico em 2012.
Os clientes queriam soluções mais complexas que usassem AWS parcial ou totalmente, enquanto nós achávamos que, como o hardware tinha ficado muito mais poderoso do que 10 anos antes, até clientes grandes iriam querer servidores mais simples e em menor quantidade.
Mas isso não era vender inteligência, era vender preço, e não entendemos a ambição financeira necessária para essa transição. Ninguém confiava em um servidor único barato e, mesmo comprando dois, faltava uma resposta para escalabilidade.
No fim, a receita se sustentou, mas não conseguimos criar uma stack de serviços gerenciados e um ecossistema de software mais rápido que a Amazon; depois que os novos desafios técnicos secaram, vendemos a empresa em 2018.
Como crescemos em bootstrapping e uma conta de hospedagem sem limite parecia um risco absurdo, o design do produto também vinha dessa mentalidade; só depois ficou claro que todo mundo estava assumindo esse risco.
A AWS pegou não só porque VCs viabilizaram produtos caros, mas porque a inteligência peculiar dela foi incorporada a uma geração de desenvolvedores de software. Só que saber quando a nuvem não é necessária e quais são as alternativas agora parece um conhecimento bem de nicho.
Há alguns problemas com os números.
Primeiro, o tráfego não se distribui uniformemente. O número de 400 milhões de page loads por mês do texto pode estar sujeito a uma regra 80/20 recursiva e, por essa conta, cerca de 205 milhões de requisições se concentrariam em 5,8 horas, dando algo como 9,7 mil requisições por segundo.
Ainda é possível com um único sistema, mas deixa de ser trivial, especialmente se você também quiser um único banco de dados sem réplicas de leitura. Mesmo com o mesmo tráfego total, o limite de banda necessário para o pico de carga fica muito maior do que a média otimista de 11 MB/s.
Segundo, latência fim a fim unidirecional só se aplica a dados em streaming. Num cold start real, sem HTTP/3, são necessárias 3 idas e voltas para a conexão TCP e pelo menos 2 para a conexão TLS, e só depois disso vêm a requisição e a resposta HTTP.
Para atender pessoas de verdade, tudo que é observável precisa acontecer em menos de 1 segundo; depois disso, cresce rapidamente a proporção de usuários que concluem que o sistema quebrou e fecham a aba.
Antigamente ajudei a operar uma bolsa de apostas: o tráfego tinha picos extremos, os requisitos de latência eram rígidos, e o volume de transações se concentrava em um trecho minúsculo da janela total do evento. Em transações em tempo real, o resultado precisava aparecer na tela em até 100 ms a partir do momento em que o usuário iniciava a ação, e a latência de ida e volta da rede corroía o orçamento de processamento do evento.
Referência: https://www.nngroup.com/articles/response-times-3-important-...
Também dá para lidar com essa carga usando uma configuração de servidor único grande, mas aí você já não está fazendo um simples servidor web, e sim um load balancer de front-end bem parrudo com servidor web embutido.
A AWS cobra caro, mas há uma engenharia enorme nos load balancers e na infraestrutura de rede, e graças a isso o restante de nós não precisa virar especialista nessa área inteira da stack.
Quantos serviços de fato precisam de alcance global? Você também criou suporte a vários idiomas?
Se você atende dentro dos EUA ou da UE, um bom servidor centralizado já consegue oferecer latência abaixo de 30 ms para toda a região.
A borda é superestimada, a menos que você tenha uma exigência global real e também precise gerenciar um banco de dados global.
Como aparece
500 Internal Server Error, parece que o autor está recebendo mais tráfego que 11 MB/s. Há uma cópia arquivada aqui: https://archive.is/UVpg0PR_END_OF_FILE_ERROR. Vários sites dizem que pode acontecer por causa de proxy, VPN ou DNS-over-HTTPS, mas no meu caso não se aplica.Acho que este texto está olhando para a coisa do jeito errado.
Uma abordagem melhor é não escale cedo demais.
Construa o quanto for necessário e, na maioria dos casos, até CDN é um custo desnecessário, desde que você não esteja pagando o imposto exagerado de banda do provedor de nuvem.
Quando problemas de desempenho começarem a aparecer, você lida com eles; e se um cavalo de trabalho comum de repente virar o unicórnio que todo mundo quer, esse é um problema bom de ter.
Se o produto for bom, os usuários tentarão de novo uma hora depois, não migrarão imediatamente para um concorrente. Se surgirem problemas de escalabilidade, dá para ir para um modelo híbrido em que só as partes intensivas em recursos escalam.
Ainda assim, se você quiser webscale desde o começo, dezenas de microsserviços, estados de falha explodindo entre eles e queimar dinheiro de VC na conta da AWS antes do primeiro cliente, fique à vontade.
Operar servidores físicos diretamente é um problema para depois, não para agora. Quando a escolha for entre uma conta de 1 milhão de dólares na AWS e um servidor único parrudo, você não vai decidir com base em um post de blog; vai estar rodando seus próprios testes.
Ao usar AWS, você também está comprando um bode expiatório. Uma grande falha em um serviço de nuvem é fácil de explicar ao chefe ou aos investidores, mas é muito mais difícil explicar que o mesmo downtime acumulado veio de erro humano da equipe.
Então fico curioso sobre como isso se encaixa na interpretação de que a nuvem é um bode expiatório.
Se a ideia é escalar verticalmente, por que SQLite? Nada impede rodar um Postgres auto-hospedado ou Supabase no mesmo servidor junto com a aplicação, e não me ocorre nenhuma desvantagem além do esforço extra de configuração
Se você seguir sem DB e mantiver todo o estado global na memória real de um único servidor grande, preservando-o como objetos dentro do processo sem idas e vindas ao Redis, tirando snapshots ocasionais da memória para o disco e usando uma linguagem multithread compilada, dá para saturar uma NIC de mais de 1 Gbit e atender o mundo inteiro a partir de uma única máquina
Também fico pensando que seria bom se houvesse casos reais de uso para uma arquitetura assim
Fora dos padrões relacionais tradicionais de persistência, a diferença de recursos pode ser grande e o Postgres pode ser melhor, mas em certos padrões arquiteturais o SQLite também pode levar vantagem
Em aplicações centradas em conteúdo, como o BusinessInsider, o padrão Baked Data baseado em SQLite pode ser melhor em custo e latência
simonw(datasette) criou muitas ferramentas e textos sobre o uso de SQLite em produção para sites centrados em conteúdo ou ricos em dados: https://simonwillison.net/2021/Jul/28/baked-data/
Faz sentido, já que o SQLite roda dentro do processo e não precisa de serialização. Ele também tem a vantagem adicional de permitir processar operações em série, o que facilita muito testes, raciocínio e construção de camadas de cache
Se não usar soquetes Unix, também há overhead de rede, mas como foi dito que é no mesmo servidor, deixo isso como observação. Na prática, é muito comum colocar o Postgres em outra máquina por isolamento, e esse também é um dos principais benefícios de um DB de rede
Ele tem todos os recursos necessários e ainda oferece mais simplicidade e velocidade. O SQLite consegue lidar com dados na casa dos terabytes, múltiplas leituras e backups em streaming em tempo real, além de ser uma implementação de SQL bastante equilibrada no geral
Eu só consideraria Postgres/MySQL quando passasse do limite de escalar verticalmente uma única máquina
https://blog.cloudflare.com/introducing-d1
Parece que muita gente, ao ver o autor focar em latência, largura de banda e custo, sente que precisa defender o status quo com base em disponibilidade e confiabilidade
Minha conclusão diante dos trade-offs não é negar as vantagens da nuvem, mas questionar se os padrões de arquitetura em nuvem que agora estão por toda parte, e as dependências que vêm com eles, são realmente indispensáveis
O contraste entre isto e aquilo é um recurso retórico para apresentar alternativas, e a solução certa depende de inúmeros fatores para cada caso de uso. É justamente graças a esses fatores que engenheiros conseguem emprego
Ainda assim, mesmo dentro do padrão proposto pelo autor, dá para resolver as preocupações de SRE. “E a disponibilidade se um único servidor morrer?” é quase um espantalho, porque a disponibilidade pode ser resolvida de maneiras diferentes das dos sistemas com que estamos acostumados, e a solução deve ser ajustada ao que realmente importa
Há uma forma de obter muito mais acrescentando só uma etapa a um orçamento enxuto: colocar a API e o DB SQLite juntos
O ideal é que a API use um formato de serialização binária de baixo overhead e conexões persistentes, enquanto a entrega web aproveita o tier gratuito de algum serviço de edge bancado por VC que queima dinheiro. No momento, o Cloudflare Workers é bem generoso e o tráfego de saída também é gratuito
O ponto central é que o SQLite consegue processar uma quantidade enorme de consultas por segundo mesmo em single thread. Como muitas operações podem ser empurradas em série, fica fácil raciocinar sobre o sistema, e o cache em memória no lado da API e a invalidação também ficam mais simples
Separar o serving web permite aproveitar o desempenho da edge nos handshakes e, em páginas estáticas, pular completamente o DB. O texto subestimou o problema do tempo de ida e volta; aplicações reais exigem mais idas e vindas do que se imagina, então isso é bastante concreto
A maior parte do uso de CPU fora do DB vem de parsing, desserialização, cópia de dados e TLS; ao remover uma grande fatia disso, dá para obter facilmente dezenas de milhares de escritas por segundo mesmo em máquinas comuns, e as leituras são ainda mais rápidas
Mesmo assim, sempre vale a pena fazer benchmarks dos gargalos típicos, especialmente I/O. Provedores muitas vezes exageram ou induzem a erro, então é preciso testar por conta própria no tier gratuito. Também é bom deixar testes de integração e benchmarks preparados para o momento em que for necessário migrar
Para resultados grandes isso é bem bom, mas espero que o próprio PostgreSQL não vire gargalo ao transformar datasets grandes em JSON
Dizem que é preciso estar na borda, perto do usuário, e reduzir a latência.
Mas, na prática, quão grande é o problema da latência?
O projeto de recomendação de livros Gnooks, operado em um servidor na Alemanha, é um exemplo: https://www.gnooks.com
Fico curioso se ele parece lento demais para alguém.
Ao longo dos últimos anos, recebi milhares de sugestões de usuários nesse projeto, mas, pelo que me lembro, ninguém levantou o tema da latência. E isso apesar de o maior grupo de usuários estar nos EUA
Por isso, sofre muito menos com problemas de latência do que as PWAs modernas, que implementam a maior parte da lógica no frontend e depois fazem várias consultas ao backend para buscar os dados necessários
Ainda assim, o site em si é ok. O problema aparece quando o site já é lento
Se fizer isso da Europa, a latência será cerca de 2 vezes a que um usuário australiano vê, o que ajuda a estimar a pior experiência
O lado bom é que dá para testar isso de forma confiável e verificar se realmente importa. Aí se chega a uma resposta concreta
O texto nem aborda disponibilidade. Um serviço rodando em uma única máquina terá tanto downtime planejado quanto downtime inesperado.
Também é preciso pensar em RPO/RTO. Quando a máquina estourar — ou melhor, se estourar — é preciso ver quanto tempo a recuperação levará e quantos dados serão perdidos.
Sobre a frase de que, se houver qualquer consulta ao banco de dados na renderização da página, será preciso voltar ao DB em us-east-1, existem também estas opções:
https://aws.amazon.com/rds/aurora/global-database/
https://aws.amazon.com/dynamodb/global-tables/
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Conce...
https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/...
Há muitas coisas parecidas, e tentar remendar a mesma solução por conta própria daria trabalho
Há 10 ou 20 anos eu teria concordado. A internet era novidade, quando um site caía as pessoas culpavam o site, e a situação piorava rapidamente. Mas hoje é mais provável que culpem primeiro o provedor de internet ou tentem de novo mais tarde.
Nem todo mundo é o Google, e sistemas mais simples têm menos chance de falhar para começo de conversa. Mantenha backups e, se estiver realmente preocupado, replique o DB para um site frio de recuperação de desastres. Para a maioria das empresas e situações que não são FAANG, isso é suficiente.
Desde que os dados não sejam perdidos, para muitas empresas isso termina como uma breve oscilação. Se a comunicação for boa e o evento for muito raro, até alguns dias fora do ar podem ser toleráveis; em alguns casos, até perda de dados pode ser suportada.
Havia um ditado de que cada nove adicional de confiabilidade dobra o custo, e isso precisa necessariamente entrar no cálculo de ROI. O quanto uma empresa realmente precisa de confiabilidade depende do mercado-alvo, e acho que a resposta padrão de TI, 100% automático, está errada
Um modelo de servidor único ou servidor duplo também tem muito menos complexidade, e é por isso que equipes de operação como a da LetsEncrypt escolheram essa arquitetura de dois servidores físicos para operar um serviço global em escala web: https://letsencrypt.org/2021/01/21/next-gen-database-servers...
Graças à latência interna muito baixa de um DB dentro do servidor ou em um DB logo ao lado, o software consegue executar consultas ao DB várias ordens de grandeza mais rápido, usar menos recursos por usuário e oferecer uma experiência de usuário mais responsiva do que serviços de DB gerenciados na prática
A complexidade cria suas próprias armadilhas, e acho que não existe webservice que nunca tenha se enrolado com isso. A própria AWS também pode causar incidentes
Não dá para dizer que VPS seja pior nesse ponto