Marcio Trindade

Rails + Unicorn + Upstart + Monit

Hoje vou mostrar como estou utilizando o deploy deste blog que é um projeto Rails com o código fonte aberto. O mesmo está rodando em um servidor linux "Ubuntu 14.04.1 LTS (Trusty Tahr)". Não vou entrar em detalhes aqui de como preparei a máquina, mas deixo a dica de que estou utilizando Ansible pra isso.

Unicorn

A configuração do unicorn que eu estou utilizando não tem muito segredo, é uma configuração simples que você encontra parecidas no github como exemplo.

/etc/unicorn/blog.rb
listen            "/tmp/blog-unicorn.sock"
logger            Logger.new($stdout)
pid               "/var/run/blog/unicorn.pid"
preload_app       true
timeout           10
worker_processes  2
working_directory "/var/www/blog/current"

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection

  child_pid = server.config[:pid].sub(".pid", "#{worker.nr}.pid")
  system("echo #{Process.pid} > #{child_pid}")
end

Configurei o unicorn para rodar com 2 workers que no meu caso é suficiente e criei um pidfile para cada um destes a fim de monitora-los logo mais. Se você estiver utilizando ActiveRecord é importante recriar as conexões com o banco de dados para cada processo.

Upstart

Se você ainda não conhece o upstart recomendo que estude um pouco o mesmo que é uma ferramenta simples baseada em eventos que transforma seu serviço em um daemon. Veja como estou utilizado-o neste blog:

/etc/init/blog
description "blog app server"

pre-start script
  mkdir -p /var/log/blog
  chown blog. /var/log/blog
  chmod 770 /var/log/blog

  mkdir -p /var/run/blog
  chown blog. /var/run/blog
  chmod 770 /var/run/blog
end script

start on runlevel [2345] and started networking
stop on runlevel [!2345] or  stopped networking

chdir /var/www/blog/current

exec sudo -u blog sh -c 'bundle exec unicorn -c /etc/unicorn/blog.rb -E production >> /var/log/blog/unicorn.log 2>&1'

respawn
respawn limit 1 10

Tendo o unicorn e o upstart configurados podemos iniciar nossa aplicação rodando start blog que o serviço já fica disponível e o stop blog para o mesmo. Simples não é mesmo? Porém ainda podemos monitorar nosso serviço, pra isso vamos utilizar o monit.

Monit

Esta é na minha opinião a melhor ferramenta pra monitoração por que além de confiável é muito simples de configurar, como podemos ver no arquivo abaixo.

/etc/monit/conf.d/blog.conf
check file blog_tmp with path /var/www/blog/shared/tmp/restart.txt
  if changed timestamp then exec "/sbin/restart blog"

check process blog_unicorn with pidfile /var/run/blog/unicorn.pid
  start program = "/sbin/start blog"
  stop program = "/sbin/stop blog"
  if 5 restarts within 5 cycles then timeout

check process blog_unicorn_0 with pidfile /var/run/blog/unicorn0.pid
  start program = "/bin/true"
  stop program = "/usr/bin/test -s /var/run/blog/unicorn0.pid && /bin/kill -QUIT `cat /var/run/blog/unicorn0.pid`"
  if mem > 200.0 MB for 1 cycles then restart
  if cpu > 30% for 3 cycles then restart
  if 5 restarts within 5 cycles then timeout

check process blog_unicorn_1 with pidfile /var/run/blog/unicorn1.pid
  start program = "/bin/true"
  stop program = "/usr/bin/test -s /var/run/blog/unicorn1.pid && /bin/kill -QUIT `cat /var/run/blog/unicorn1.pid`"
  if mem > 200.0 MB for 1 cycles then restart
  if cpu > 30% for 3 cycles then restart
  if 5 restarts within 5 cycles then timeout

Desta forma além do daemon pra cuidar da nossa app ainda temos o monit verificando o consumo de memória e cpu e ganhamos um restart simples bastando executar um touch tmp/restart.txt.

Este artigo tem me ajudado como consulta para os meus projetos e espero que ajude você também, se tiver alguma sugestão por favor me mande nos comentários. Abaixo os links citados neste post: