OpenFreeMap compartilha a experiência de suportar 100 mil requisições por segundo
(blog.hyperknot.com)- OpenFreeMap processou com sucesso 100 mil requisições por segundo e 300 milhões de requisições de tráfego diário
- A súbita popularidade do Wplace.live e requisições em massa automatizadas foram a causa do pico de tráfego
- A taxa de cache do CDN da Cloudflare alcançou 99,4%, enquanto o servidor lidou sem problemas com os 1.000 rps restantes
- Como resultado, ocorreram apenas falhas pequenas, como a falta de tiles, e o serviço continuou operando normalmente na maior parte do tempo
- No futuro, serão anunciadas melhorias no gerenciamento automático de tráfego, incluindo limitação de largura de banda baseada no referer
A experiência de 10 meses do OpenFreeMap e da resposta ao tráfego em larga escala
OpenFreeMap vem tendo uma operação muito estável nos últimos 10 meses. A confiabilidade do sistema foi comprovada pelo suporte de largura de banda da Cloudflare, a estabilidade dos servidores Hetzner, o serviço de tiles no Btrfs e a eficiência do nginx. No entanto, em um dia, recebemos um relatório de que alguns tiles não carregavam. Normalmente isso era causado por bug de algoritmo, mas desta vez encontrou-se, no log do nginx, o erro open() "Too many open files".
Ao verificar com a ferramenta de monitoramento de tráfego, observou-se que houve 3 bilhões de requisições em 24 horas e que até arquivos de tiles pequenos geraram 215 TB de tráfego. Houve recentemente um pico de 30 milhões de requisições em 5 minutos, atingindo 100 mil requisições por segundo. Este volume de tráfego custaria mais de US$ 6 milhões por mês em serviços comerciais de mapas.
No painel da Cloudflare, 96% responderam com 200 OK e apenas 3,6% foram anômalos (206 Partial Content). A maior parte das requisições foi servida normalmente, e, excluindo alguns tiles ausentes, o sistema inteiro funcionou bem.
Causa do pico de tráfego: Wplace.live
A causa desse pico foi o novo site de desenho colaborativo Wplace.live. Logo após seu lançamento, chegou uma grande quantidade de usuários, e ele foi projetado para usar mapas baseados no OpenFreeMap. Usuários usaram ferramentas automatizadas (como Puppeteer/Chromium, rotação de IP etc.) para burlar o limite de 1 pixel/30 segundos, gerando requisições em massa.
O responsável destacou, com base em experiência anterior com o Neal.fun, a importância da comunicação prévia antes de um aumento de tráfego. Como desta vez houve impacto na operação do serviço, aplicaram-se regras da Cloudflare pela primeira vez para bloqueio. No futuro, busca-se uma solução de controle automático de tráfego baseada em referer ou cabeçalho personalizado (incluindo o uso da API da Cloudflare).
Suporte da Cloudflare e o desempenho da arquitetura do OpenFreeMap
A Cloudflare aprovou rapidamente o apoio de largura de banda em até 48 horas, incluindo fim de semana, e houve até uma discussão com engenheiros sobre a adequação da arquitetura. Mesmo sendo uma empresa grande, demonstrou resposta bastante flexível.
O operador destacou que alcançou 99,4% de taxa de cache no CDN e que o servidor suportou sem dificuldade carga de 1.000 rps. Para um serviço que oferece atualização de dados semanal, isso é um desempenho bastante alto.
Comunicação com o desenvolvedor do Wplace.live e proposta de solução
Posteriormente, foi feito contato com os desenvolvedores do Wplace.live e entendeu-se que eles não estavam preparados para o aumento repentino de 2 milhões de usuários. Discutiu-se a oferta de instâncias de auto-hospedagem do OpenFreeMap para eles, com o objetivo de reduzir a concentração de tráfego e aumentar a eficiência.
Além disso, o fato de 3 bilhões de requisições ocorrerem para apenas 2 milhões de usuários reais sugere que predominou requisição em massa baseada em script. Como usuários comuns fazem entre 10 e 20 requisições, recomendou-se ajustar a política do serviço para impedir requisições automatizadas desnecessárias.
Melhorias e aprendizados futuros
O operador anunciou duas melhorias:
-
Limite de largura de banda baseado em referer
- A partir do Cloudflare, será implementada a limitação de solicitações por referer em faixas de 100 milhões a 200 milhões por 24 horas, entre outros cenários
- Os aplicativos nativos serão direcionados a usar cabeçalho personalizado
-
Tratamento de tiles ausentes e melhoria da configuração do servidor
- Serão tomadas medidas para evitar que tiles vazios sejam gerados por configuração incorreta de servidor
O OpenFreeMap é mantido atualmente por doações de US$ 500 por mês. Os custos de infraestrutura já estão cobertos, mas o desenvolvimento novo depende do tempo disponível de pessoa física. Com mais apoio, é possível ampliar a velocidade de desenvolvimento e a estabilidade do serviço.
É possível participar apoiando o projeto pelo GitHub: https://github.com/sponsors/hyperknot
1 comentários
Opinião no Hacker News
Acho que algumas imagens foram pintadas por script kiddies. Como o site permite apenas 1 pixel a cada 30 segundos por usuário, acho que a automação foi feita abrindo um novo navegador com Puppeteer ou Chromium, clicando em um pixel e fechando o navegador depois. Talvez tenham feito até rotação de IP, embora talvez nem tenha sido necessário. Não subestimemos o fato de isso ter crescido em escala absurda da noite para o manhã. Comentei com algumas pessoas sobre um desenho perto de casa e, sem citar o site, todos entenderam imediatamente do que eu estava falando. Parece que as pessoas gostam bastante desse tipo de projeto parecido com /r/place a cada alguns anos, e desta vez o fato de poder desenhar em um mapa do mundo inteiro — e até perto da sua própria casa — parece ter sido uma boa recepção
Fiquei curioso sobre qual seria a diferença se os arquivos pmtiles estáticos fossem lidos diretamente no maplibre. Quando buscava pmtiles da Bunnycdn por range request, a velocidade de resposta ficou praticamente igual à de receber de um servidor de tiles real.
Penso que o wplace poderia resolver a demanda inteira com um único pmtiles estático customizado. Não seria o caso de precisar processar 150 GB de dados OSM.
Link relacionado compartilhado
Obrigado por essa explicação detalhada e transparência. Estou avaliando colocar o OpenFreeMap no mapa de incidentes da StatusGator no lugar do MapTiler.
Só pela screenshot parecia que uma única VPS seria suficiente, e parecia um design muito complexo. Depois percebi que os pixels estavam sobre o mapa do mundo inteiro. Fico curioso sobre qual seria a vazão máxima de requisições. Pode ser algo no limite do que um web server fácil de benchmarka reria suportar. Claro, pelo perfil do app, pode haver queda de performance relevante. Com 64 pixels por km, em cor sem compressão, seria necessário 8 TB para cobertura global (problema de longo prazo!). A máquina de 10 TB da Hetzner custa 20 euros por mês, então o cache parece essencial. O wplace usa um PNG de 1000x1000 pixels na camada de desenho, e a arte aparece imediatamente, mas o mapa em si é muito lento e há trechos que nem carregam.
Parece que o gargalo foi o limite de arquivos abertos, me pergunto se só elevá-lo já teria dado conta. Entendo bloquear tráfego spam, mas teoricamente, só aumentar esse limite não seria suficiente?
Fico me perguntando se sites sem cache implementado são sempre assim por "preguiça". Se o wplace.live envia tanto tráfego para o openfreemap, com apenas um servidor de cache próprio não seria possível servir mais rápido (ou semelhante) do que o openfreemap?
O openfreemap está por trás de uma CDN, e no site está escrito assim: "Instância pública gratuita, sem limite de visualizações/requisições, sem necessidade de cadastro/cookie/chave API. Custos são cobertos por doação. Uso comercial permitido". Pela leitura, dá impressão de que é para usar diretamente. Não parece haver necessidade de colocar servidor de cache na frente da CDN. Faz sentido conferir a largura de banda e avaliar, mas em situação viral inesperada talvez esteja ocupado com outras tarefas.
Posso responder a essa pergunta com precisão: é uma questão de prioridade. Eu opero um site de leilões bastante popular e os tiles do mapa vêm do Stadia Maps. Pago 80 dólares por mês, e sei que seria mais barato fornecer tiles em proxy a partir de cache, mas como sempre há algo mais urgente eu ainda não fiz esse trabalho de cache.
O volume de dados aqui é gigantesco. Houve um pico de 56 Gbps (56 servidores consumindo 100% do tráfego!). Não é algo que um único servidor de cache cobre. Isso precisa de uma rede CDN (tipo Cloudflare) para suportar.
Parece um site divertido e sem fins lucrativos. O foco de um site desses costuma ser "fazer funcionar" e, não em primeiro lugar, suportar tráfego em massa. Os usuários dobraram em uma noite e o time de manutenção parece ser uma ou poucas pessoas.
Eu nunca usei a Cloudflare e também não sou acostumado com tecnologia de web map. Se o site fornece principalmente arquivos estáticos, me pergunto por que continuar usando a Hetzner. Será que não dá para migrar tudo para Cloudflare Pages?
A limitação baseada em referrer me parece uma escolha estranha. Se um usuário legítimo faz 10 a 20 requisições por minuto, não bastaria limitar a 100 por minuto por IP (cinco vezes a média) para barrar a maioria? Ou com poucos usuários maliciosos não seria possível bloquear via padrão JA4/JA3?
Também existe o caso de alguém querer explorar vários pontos da Terra de verdade. Lembro de ter ficado meio dia navegando no Google Earth. Acho que limitar por referrer é melhor, e para usuários com muito tráfego, você pode recomendar self-hosting em vez da instância pública.
Limitadores por referrer é um bom primeiro passo (talvez a mensagem da página inicial também precise mudar). Rastrear consumo por site é mais eficiente. No lado do site, dá para pedir mudança de padrão de uso, mas para usuário individual fica difícil. Limitador por IP também ajudaria, mas se for muito baixo não teria efeito nesse cenário.
Achei que o bloqueio ficou muito bom. Isso é ataque DDoS. Foi bom não ter uma taxa extra de banda, porque teria sido um ataque realmente 'esvaziando a carteira'.
O hit rate de cache está altíssimo. Fico curioso se existe alguma técnica específica implementada para isso.
Estruturei todo o caminho e os location blocks pensando em cache. Se quiser, confira o exemplo de nginx.conf.