Como eu deixei meu site lento e mais caro
Como analisei a lentidão no meu site e corrige isolando cada ponto.
(Enquanto escrevo esse post, estou deletando instancias na digital ocean...)
Desde que lancei meu novo blog, tem algo que sempre me incomodava nele, e não era o fato de eu nunca ter tirado o favicon do Svelte, era o tempo de carregamento.
Eu fiz um post falando sobre as tecnologias que utilizei para criar meu blog e resumindo foram: Svelt(Sveltkit), Strapi e deploy na Digital Ocean.
Começando a investigar as causas exclui o front end da equação, desconfiei do droplet que utilizei, e pensei -Pode estar "gargalando", embora analisando as métricas coletadas, não chegava a tanto, mas resolvi tentar uma coisa, resolvi tirar o banco de dados da máquina e deixa-lo em uma instância propria (um RDS da Digital Ocean), nesse momento, que eu vou acessar a máquina para fazer o dump dos dados eu percebo que não consigo acessar o Postgres. Depois de alguns minutos, verifico as variáveis de ambiente do projeto para verificar as variáveis de ambiente e percebo que eu estava usando SQLITE.
Como o serviço da DO não dá suporte a esse tipo de base de dados, eu resolvi mudar tudo para Postgres, recriar a base e migrar os dados para poder utilizar o serviço dedicado.
Tive alguns problemas para migrar os dados, o Strapi não oferece uma solução para migrar os dados, embora a estrutura seja totalmente "migravel". Fazer isso manualmente era maçante, então criei uma ferramenta para migrar os dados de SQLITE para Postgres (e vai sair um post sobre já já).
Após todos os dados migrados, configurei o Strapi para utilizar a nova base de dados e comecei os testes, até que de repente ... tive praticamente o mesmo resultado.
Sim, todo esse trabalho e ainda com uma resposta de mais de 1.5 segundos.
Então, resolvi fazer a coisa que deveria ter feito desde o início: desistir Um trace da API o mais detalhado possível.
Definido então e resolvi utilizar o Sentry para me ajudar, e de cara um problema: Não achei o plugin de trace para o Strapi (apenas para captura de erros estava disponível), então la fui eu estudar mais afundo o Strapi para entender como eu poderia implementar o trace.
Algum tempo (e bugs) depois consegui ter o trace funcionando e ao rodar a query eu me assustei quando vi isso:
Esses 4 segundos foram bem extremos, mas a requisição saiu do local e bateu no banco de dados na DO.
O Sentry tem um detalhamento incrível e me permitiu ver as querys executadas e o tempo que estavam levando, até que cheguei no meu gargalo:
select "t0".*, "t0"."id" from "posts" as "t0" where ("t0"."published_at" is not null) limit $1
Essa query era a minha maior ofensora e se pensarmos bem ela é um simples select * from posts limit 6
, então por que demora tanto?
Baixei um client do Postgres e conectei na minha base de dados remota, por que na minha cabeça o problema ja era o Strapi e eu ja estava pensando e substitui-lo, porem iria fazer um teste antes, e esse foi o resultado do teste:
Tudo bem, talvez você já tenha entendido tudo agora, ou talvez antes, mas para mim ficou claro agora, tive a sensação de ter parado no tempo e de repente encontrado a resposta, esse GIF ilustra bem o sentimento:
Vamos rapidamente repassar tudo que fiz até aqui:
- Identificar a fonte macro da lentidão.
- Testei localmente para reproduzir o comportamento de produção.
- Troquei componentes que poderiam ser ofensores (Banco de dados).
- Trace na aplicação especifica com erro.
- Isolar e testar separadamente os componentes envolvidos.
E agora vamos ao real problema: A região onde a máquina foi criada vs a região onde o banco de dados foi criado.
Por algum motivo, eu criei o Droplet (a máquina) em Amsterdam, isso ja era suficiente para criar toda lentidão de quando eu ainda usava o SQLITE como banco de dados.
Para confirmar essa hipótese, eu utilizei uma ferramenta propria da DO para fazer testes de velocidade e latência:
http://speedtest-ams3.digitalocean.com e esse foi o resultado:
Assim que percebi, rapidamente fui trocar a região, na DO isso não é tão "plugavel" como na AWS, mas o processo foi bem simples: Criar uma Snapshot da droplet atual, mudar a região na Snapshot e criar uma Droplet com base na Snapshot, por fim, bastou eu atualizar o novo IP no DNS do domínio e esse foi meu resultado:
Tivemos um ganho de mais de 60% no tempo da requisição!
Isso é fantástico e nesse momento eu fiquei extremamente feliz, todo o processo que durou vários dias foram "pagos" com esse resultado.
Ah e se tiver alguma dúvida ou quiser me xingar por usar SQLITE em produção, fica à vontade nos comentários!
Caso queira criar uma conta na Digital Ocean, utilize esse cupom e ganhe 25 dólares de desconto: https://m.do.co/c/10755563c153