Gerenciando uma aplicação Ruby on Rails no Heroku

Com o Heroku é possível gerenciar deploys, ter métricas e utilizar Addons sem se preocupar com servidor para sua aplicação. Veja como gerenciar uma aplicação Ruby on Rails neste serviço de infraestrutura.
Kevin Santos | 17 de novembro de 2020

Há muito tempo trabalho com Heroku, o serviço de infraestrutura mais simples que já vi. Com ele você consegue gerenciar deploys, ter métricas, utilizar seus Addons e não se preocupar com servidor para sua aplicação, coisa que você vai precisar fazer se usar um Google Cloud ou AWS. Após fazer deploy de aplicação Ruby on Rails no Heroku, descobri algumas coisas que são fundamentais na hora de manter a aplicação na plataforma.

Addons

O Heroku possui um sistema de Addons, que são serviços de terceiros facilmente configuráveis. Para todo o caso, há sempre alguns Addons que são necessários se você quiser ter uma visão da sua aplicação:

  1. Bugsnag: Sistema de visualização de exceções ocorridas na sua aplicação. Se caso algum erro ocorrer na sua aplicação, vale checar esse Addon, pois ele provavelmente estará lá. Ele também funciona em algumas outras linguagens como PHP, JS e Go;

  2. LogEntries: Sistema de visualização e armazenamento de Logs. Uma aplicação precisa de Logs e o LogEntries supre perfeitamente essa parte. Ele conta com um sistema de busca, podendo agrupar por host, IP, path e etc, te dando mais controle e visibilidade do que está acontecendo na aplicação.

  3. NewRelic: Um APM (Application Performance Monitoring) para sua aplicação. Isso é fundamental, já que um APM consegue mostrar onde sua aplicação mostra lentidão, N+1 queries, quais as requests mais chamadas e toda informação que você precisa para melhorá-la.

Vale lembrar que todos esses Addons são gratuitos (com suas limitações), o que ajuda caso você esteja começando sua aplicação e quer zero custo. As versões pagas se mostram significativamente melhores. Caso você também esteja usando o Dyno Free do Heroku, vale usar o Addon Librato, assim você consegue ter as mesmas métricas que o heroku disponibiliza nos Dynos Pagos.

Dynos

Os Dynos são máquinas que hospedam sua aplicação. ‘Por baixo dos panos’, o Heroku usa a AWS para manter tudo isso, porém nós sequer chegamos a ver essa infraestrutura e tudo que gerenciamos são os Dynos e o poder deles. Na documentação do Heroku temos um grande detalhamento do que cada um é capaz. Não há uma regra clara para qual escolher, mas recomendo sempre olhar a sua necessidade atual e ir aumentando o tipo do Dyno conforme sua aplicação cresce.

BlogPost_17.11.2020_Gerenciando uma aplicação Ruby on Rails no Heroku.png

Por exemplo: você está começando sua aplicação e não recebe quase nada de requisições? Comece usando o Hobby. Sua aplicação já recebe uma média quantidade de requisições? Vale usar o Standard 1x e começar a usar o escalonamento horizontal automático, onde o Heroku aumenta e diminui a quantidade de Dynos de acordo com sua necessidade.

Claro que antes de aumentar o tipo do Dyno, vale tentar melhorar a aplicação ao máximo para não gerar custos desnecessários, como colocar um Dyno do tipo Performance M, porque sua aplicação está consumindo muita memória sem antes entender o porquê desse alto consumo.

Gerenciamento com Ruby on Rails

Dentro do Heroku, conseguimos gerenciar o quanto nossa aplicação está usando de memória nos Dynos, quando estamos em uma aplicação Rails, o que nos permite sentir se nossa aplicação precisa de um Dyno melhor ou uma maior quantidade de Dynos.

No Rails temos o Puma e com ele os Workers, configurando esses Workers podemos controlar a quantidade de memória média usada, por exemplo:

  • Se com 2 Workers, sua aplicação usa 1 Gb de RAM, logo 4 Workers irão usar 2 Gb de RAM

Vale ressaltar que esse tipo de métrica é mais visível depois da aplicação estar sendo usada há algum tempo.

Além dos Workers temos as Threads. As Threads podem virar um problema quando olhamos para o banco de dados porque se temos 2 Workers e 5 Threads, temos, então, 10 conexões no banco de dados. Se você também multiplicar isso por Dyno, podemos ficar com centenas de conexões, já que em cada Dyno temos 2 Workers.

Logo, se seu banco tiver 100 conexões disponíveis e você tiver 2 Dynos, 5 Workers em cada Dyno e 10 Threads em cada Worker, você terá 100 conexões no banco de dados. É recomendável sempre deixar algumas conexões disponíveis, pois caso você entre no console do Rails, irá contar como uma conexão.

Caso sua aplicação esteja sofrendo com conexões de banco de dados, vale dar uma olhada nos Build Packs e utilizar um Pool de conexões do banco de dados.

Build Packs

Os Build Packs são, basicamente, um processo, código ou configuração que vai na imagem que o Heroku irá criar ao fazer deploy da sua aplicação, como o Build Pack do Ruby, que será necessário para sua aplicação ser criada.

Geralmente, os Build Packs que vem com o Heroku já são o suficiente para sua aplicação rodar, porém temos mais que ajudam sua aplicação a escalar:

  1. Jemalloc: Caso sua aplicação esteja sofrendo com alto consumo de memória, esse Build Pack ajuda a diminuir drasticamente o uso de memória dentro do Heroku. Inclusive recomendo este artigo detalhando mais sobre esse recurso com exemplos reais.

  2. PgBouncer: Se sua aplicação precisa de várias conexões com o banco de dados, e seu banco não é tão robusto, esse Build Pack é perfeito para criar um pool de conexões e distribuir entre os dynos, workers e threads - diminuindo de 300 para 50 conexões, por exemplo.

Vale lembrar também que esses Build Packs servem para casos onde sua aplicação precisa escalonar mais, raramente uma aplicação pequena irá precisar.

Seguindo essas dicas, você terá uma aplicação robusta, escalável, gastando pouco. Há casos mais específicos que vão sair do padrão, porém para a maioria das aplicações, essas dicas servem perfeitamente.

Veja também nosso FAQ com tudo o que você precisa saber sobre Ruby.

Kevin Santos
Software Engineer | Arquitetura de software, infraestrutura, desenvolvimento web e mobile. Procurando a solução certa pra cada problema. Programador até nas horas vagas.